summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/docs/theme/assets/css/jazzy.css.scss1
-rw-r--r--platform/darwin/mbgl/storage/reachability.h95
-rw-r--r--platform/darwin/mbgl/storage/reachability.m (renamed from platform/darwin/src/reachability.m)10
-rw-r--r--platform/darwin/mbgl/util/image+MGLAdditions.hpp12
-rw-r--r--platform/darwin/resources/de.lproj/Foundation.strings291
-rw-r--r--platform/darwin/resources/de.lproj/Foundation.stringsdict38
-rw-r--r--platform/darwin/resources/es.lproj/Foundation.stringsdict54
-rw-r--r--platform/darwin/resources/fr.lproj/Foundation.stringsdict54
-rw-r--r--platform/darwin/resources/ja.lproj/Foundation.strings291
-rw-r--r--platform/darwin/resources/pl.lproj/Foundation.stringsdict60
-rw-r--r--platform/darwin/resources/pt-BR.lproj/Foundation.stringsdict54
-rw-r--r--platform/darwin/resources/ru.lproj/Foundation.stringsdict60
-rw-r--r--platform/darwin/resources/sv.lproj/Foundation.strings291
-rw-r--r--platform/darwin/resources/sv.lproj/Foundation.stringsdict54
-rw-r--r--platform/darwin/resources/uk.lproj/Foundation.stringsdict60
-rw-r--r--platform/darwin/resources/vi.lproj/Foundation.strings291
-rw-r--r--platform/darwin/resources/zh-Hans.lproj/Foundation.strings291
-rw-r--r--platform/darwin/resources/zh-Hant.lproj/Foundation.strings291
-rwxr-xr-xplatform/darwin/scripts/check-public-symbols.js83
-rw-r--r--platform/darwin/scripts/generate-style-code.js52
-rw-r--r--platform/darwin/scripts/update-examples.js28
-rw-r--r--platform/darwin/src/MGLAccountManager.h9
-rw-r--r--platform/darwin/src/MGLAccountManager.m2
-rw-r--r--platform/darwin/src/MGLAnnotation.h6
-rw-r--r--platform/darwin/src/MGLAttributionInfo.h10
-rw-r--r--platform/darwin/src/MGLAttributionInfo.mm20
-rw-r--r--platform/darwin/src/MGLAttributionInfo_Private.h6
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.h31
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.mm24
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.h233
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.mm112
-rw-r--r--platform/darwin/src/MGLClockDirectionFormatter.h9
-rw-r--r--platform/darwin/src/MGLClockDirectionFormatter.m8
-rw-r--r--platform/darwin/src/MGLCompassDirectionFormatter.h9
-rw-r--r--platform/darwin/src/MGLCompassDirectionFormatter.m20
-rw-r--r--platform/darwin/src/MGLConversion.h135
-rw-r--r--platform/darwin/src/MGLCoordinateFormatter.h11
-rw-r--r--platform/darwin/src/MGLCoordinateFormatter.m16
-rw-r--r--platform/darwin/src/MGLDistanceFormatter.h26
-rw-r--r--platform/darwin/src/MGLDistanceFormatter.m35
-rw-r--r--platform/darwin/src/MGLFeature.h80
-rw-r--r--platform/darwin/src/MGLFeature.mm30
-rw-r--r--platform/darwin/src/MGLFeature_Private.h4
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.h124
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.mm57
-rw-r--r--platform/darwin/src/MGLForegroundStyleLayer.h8
-rw-r--r--platform/darwin/src/MGLFoundation.h5
-rw-r--r--platform/darwin/src/MGLFoundation.mm4
-rw-r--r--platform/darwin/src/MGLFoundation_Private.h5
-rw-r--r--platform/darwin/src/MGLGeometry.h6
-rw-r--r--platform/darwin/src/MGLGeometry.mm10
-rw-r--r--platform/darwin/src/MGLGeometry_Private.h4
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h185
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.mm106
-rw-r--r--platform/darwin/src/MGLMapCamera.h7
-rw-r--r--platform/darwin/src/MGLMapCamera.mm8
-rw-r--r--platform/darwin/src/MGLMultiPoint.h32
-rw-r--r--platform/darwin/src/MGLMultiPoint.mm10
-rw-r--r--platform/darwin/src/MGLNetworkConfiguration.h10
-rw-r--r--platform/darwin/src/MGLOfflinePack.h34
-rw-r--r--platform/darwin/src/MGLOfflinePack.mm77
-rw-r--r--platform/darwin/src/MGLOfflinePack_Private.h54
-rw-r--r--platform/darwin/src/MGLOfflineRegion_Private.h2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.h130
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm82
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.h3
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.mm46
-rw-r--r--platform/darwin/src/MGLOverlay.h8
-rw-r--r--platform/darwin/src/MGLPointAnnotation.h10
-rw-r--r--platform/darwin/src/MGLPointAnnotation.mm2
-rw-r--r--platform/darwin/src/MGLPointCollection.h12
-rw-r--r--platform/darwin/src/MGLPointCollection.mm4
-rw-r--r--platform/darwin/src/MGLPolygon+MGLAdditions.m6
-rw-r--r--platform/darwin/src/MGLPolygon.h27
-rw-r--r--platform/darwin/src/MGLPolygon.mm10
-rw-r--r--platform/darwin/src/MGLPolyline.h23
-rw-r--r--platform/darwin/src/MGLPolyline.mm12
-rw-r--r--platform/darwin/src/MGLRasterSource.h32
-rw-r--r--platform/darwin/src/MGLRasterSource.mm6
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.h59
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.mm56
-rw-r--r--platform/darwin/src/MGLShape.h30
-rw-r--r--platform/darwin/src/MGLShape.mm4
-rw-r--r--platform/darwin/src/MGLShapeCollection.h16
-rw-r--r--platform/darwin/src/MGLShapeCollection.mm2
-rw-r--r--platform/darwin/src/MGLShapeSource.h52
-rw-r--r--platform/darwin/src/MGLShapeSource.mm24
-rw-r--r--platform/darwin/src/MGLShapeSource_Private.h3
-rw-r--r--platform/darwin/src/MGLSource.h11
-rw-r--r--platform/darwin/src/MGLSource_Private.h14
-rw-r--r--platform/darwin/src/MGLStyle.h110
-rw-r--r--platform/darwin/src/MGLStyle.mm46
-rw-r--r--platform/darwin/src/MGLStyleLayer.h14
-rw-r--r--platform/darwin/src/MGLStyleLayer.h.ejs14
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm2
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm.ejs66
-rw-r--r--platform/darwin/src/MGLStyleLayer_Private.h5
-rw-r--r--platform/darwin/src/MGLStyleValue.h391
-rw-r--r--platform/darwin/src/MGLStyleValue.mm254
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h661
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h457
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm312
-rw-r--r--platform/darwin/src/MGLTilePyramidOfflineRegion.h14
-rw-r--r--platform/darwin/src/MGLTilePyramidOfflineRegion.mm8
-rw-r--r--platform/darwin/src/MGLTileSource.h62
-rw-r--r--platform/darwin/src/MGLTileSource.mm14
-rw-r--r--platform/darwin/src/MGLTileSource_Private.h10
-rw-r--r--platform/darwin/src/MGLTypes.h4
-rw-r--r--platform/darwin/src/MGLValueEvaluator.h14
-rw-r--r--platform/darwin/src/MGLVectorSource.h10
-rw-r--r--platform/darwin/src/MGLVectorSource.mm4
-rw-r--r--platform/darwin/src/MGLVectorStyleLayer.h42
-rw-r--r--platform/darwin/src/NSArray+MGLAdditions.mm6
-rw-r--r--platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm113
-rw-r--r--platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm10
-rw-r--r--platform/darwin/src/NSData+MGLAdditions.mm4
-rw-r--r--platform/darwin/src/NSDate+MGLAdditions.h6
-rw-r--r--platform/darwin/src/NSDate+MGLAdditions.mm7
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.h3
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm78
-rw-r--r--platform/darwin/src/NSPredicate+MGLAdditions.mm112
-rw-r--r--platform/darwin/src/NSString+MGLAdditions.h2
-rw-r--r--platform/darwin/src/NSString+MGLAdditions.m2
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.h8
-rw-r--r--platform/darwin/src/headless_backend_cgl.cpp64
-rw-r--r--platform/darwin/src/headless_backend_eagl.mm44
-rw-r--r--platform/darwin/src/headless_display_cgl.cpp60
-rw-r--r--platform/darwin/src/http_file_source.mm27
-rw-r--r--platform/darwin/src/image.mm169
-rw-r--r--platform/darwin/src/logging_nslog.mm (renamed from platform/darwin/src/log_nslog.mm)2
-rw-r--r--platform/darwin/src/nsthread.mm2
-rw-r--r--platform/darwin/src/run_loop.cpp17
-rw-r--r--platform/darwin/src/string_nsstring.mm2
-rw-r--r--platform/darwin/test/MGLAttributionInfoTests.m26
-rw-r--r--platform/darwin/test/MGLBackgroundStyleLayerTests.mm123
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.mm537
-rw-r--r--platform/darwin/test/MGLClockDirectionFormatterTests.m26
-rw-r--r--platform/darwin/test/MGLCodingTests.m200
-rw-r--r--platform/darwin/test/MGLCompassDirectionFormatterTests.m32
-rw-r--r--platform/darwin/test/MGLCoordinateFormatterTests.m16
-rw-r--r--platform/darwin/test/MGLDistanceFormatterTests.m30
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift16
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm240
-rw-r--r--platform/darwin/test/MGLFeatureTests.mm82
-rw-r--r--platform/darwin/test/MGLFillStyleLayerTests.mm343
-rw-r--r--platform/darwin/test/MGLGeometryTests.mm20
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.mm656
-rw-r--r--platform/darwin/test/MGLNSStringAdditionsTests.m18
-rw-r--r--platform/darwin/test/MGLOfflinePackTests.m6
-rw-r--r--platform/darwin/test/MGLOfflineRegionTests.m4
-rw-r--r--platform/darwin/test/MGLOfflineStorageTests.mm (renamed from platform/darwin/test/MGLOfflineStorageTests.m)92
-rw-r--r--platform/darwin/test/MGLPredicateTests.mm249
-rw-r--r--platform/darwin/test/MGLRasterStyleLayerTests.mm279
-rw-r--r--platform/darwin/test/MGLShapeSourceTests.mm76
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.m10
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.mm.ejs79
-rw-r--r--platform/darwin/test/MGLStyleTests.mm45
-rw-r--r--platform/darwin/test/MGLStyleValueTests.m102
-rw-r--r--platform/darwin/test/MGLStyleValueTests.swift289
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm1924
-rw-r--r--platform/darwin/test/MGLTileSetTests.mm26
-rw-r--r--platform/darwin/test/MGLVersionNumber.m15
162 files changed, 10223 insertions, 3319 deletions
diff --git a/platform/darwin/docs/theme/assets/css/jazzy.css.scss b/platform/darwin/docs/theme/assets/css/jazzy.css.scss
index 6b4dffc879..ad0a3b7082 100644
--- a/platform/darwin/docs/theme/assets/css/jazzy.css.scss
+++ b/platform/darwin/docs/theme/assets/css/jazzy.css.scss
@@ -383,6 +383,7 @@ pre code {
.nav-group-task[data-name="MGLMultiPoint"],
.nav-group-task[data-name="MGLShape"],
.nav-group-task[data-name="MGLSource"],
+.nav-group-task[data-name="MGLStyleFunction"],
.nav-group-task[data-name="MGLStyleLayer"],
.nav-group-task[data-name="MGLTileSource"],
.nav-group-task[data-name="MGLVectorStyleLayer"] {
diff --git a/platform/darwin/mbgl/storage/reachability.h b/platform/darwin/mbgl/storage/reachability.h
new file mode 100644
index 0000000000..e38c9b1e20
--- /dev/null
+++ b/platform/darwin/mbgl/storage/reachability.h
@@ -0,0 +1,95 @@
+/*
+ Copyright (c) 2011, Tony Million.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+
+
+/**
+ * Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X.
+ *
+ * @see http://nshipster.com/ns_enum-ns_options/
+ **/
+#ifndef NS_ENUM
+#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
+#endif
+
+extern NSString *const kMGLReachabilityChangedNotification;
+
+typedef NS_ENUM(NSInteger, NetworkStatus) {
+ // Apple NetworkStatus Compatible Names.
+ NotReachable = 0,
+ ReachableViaWiFi = 2,
+ ReachableViaWWAN = 1
+};
+
+@class MGLReachability;
+
+typedef void (^NetworkReachable)(MGLReachability * reachability);
+typedef void (^NetworkUnreachable)(MGLReachability * reachability);
+
+
+@interface MGLReachability : NSObject
+
+@property (nonatomic, copy) NetworkReachable reachableBlock;
+@property (nonatomic, copy) NetworkUnreachable unreachableBlock;
+
+@property (nonatomic, assign) BOOL reachableOnWWAN;
+
+
++(instancetype)reachabilityWithHostname:(NSString*)hostname;
+// This is identical to the function above, but is here to maintain
+// compatibility with Apples original code. (see .m)
++(instancetype)reachabilityWithHostName:(NSString*)hostname;
++(instancetype)reachabilityForInternetConnection;
++(instancetype)reachabilityWithAddress:(void *)hostAddress;
++(instancetype)reachabilityForLocalWiFi;
+
+-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref;
+
+-(BOOL)startNotifier;
+-(void)stopNotifier;
+
+-(BOOL)isReachable;
+-(BOOL)isReachableViaWWAN;
+-(BOOL)isReachableViaWiFi;
+
+// WWAN may be available, but not active until a connection has been established.
+// WiFi may require a connection for VPN on Demand.
+-(BOOL)isConnectionRequired; // Identical DDG variant.
+-(BOOL)connectionRequired; // Apple's routine.
+// Dynamic, on demand connection?
+-(BOOL)isConnectionOnDemand;
+// Is user intervention required?
+-(BOOL)isInterventionRequired;
+
+-(NetworkStatus)currentReachabilityStatus;
+-(SCNetworkReachabilityFlags)reachabilityFlags;
+-(NSString*)currentReachabilityString;
+-(NSString*)currentReachabilityFlags;
+
+@end
diff --git a/platform/darwin/src/reachability.m b/platform/darwin/mbgl/storage/reachability.m
index 8abcf5ae6d..2030e7ef71 100644
--- a/platform/darwin/src/reachability.m
+++ b/platform/darwin/mbgl/storage/reachability.m
@@ -25,7 +25,7 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-#import <mbgl/platform/darwin/reachability.h>
+#import <mbgl/storage/reachability.h>
#import <sys/socket.h>
#import <netinet/in.h>
@@ -242,10 +242,10 @@ static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkRea
// This is for the case where you flick the airplane mode;
// you end up getting something like this:
-//Reachability: WR ct-----
-//Reachability: -- -------
-//Reachability: WR ct-----
-//Reachability: -- -------
+// Reachability: WR ct-----
+// Reachability: -- -------
+// Reachability: WR ct-----
+// Reachability: -- -------
// We treat this as 4 UNREACHABLE triggers - really apple should do better than this
#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)
diff --git a/platform/darwin/mbgl/util/image+MGLAdditions.hpp b/platform/darwin/mbgl/util/image+MGLAdditions.hpp
new file mode 100644
index 0000000000..c738b4523d
--- /dev/null
+++ b/platform/darwin/mbgl/util/image+MGLAdditions.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <mbgl/util/image.hpp>
+
+#include <CoreGraphics/CGImage.h>
+
+// Creates a CGImage from a PremultipliedImage, taking over the memory ownership.
+CGImageRef CGImageFromMGLPremultipliedImage(mbgl::PremultipliedImage&&);
+
+// Creates a PremultipliedImage by copying the pixels of the CGImage.
+// Does not alter the retain count of the supplied CGImage.
+mbgl::PremultipliedImage MGLPremultipliedImageFromCGImage(CGImageRef);
diff --git a/platform/darwin/resources/de.lproj/Foundation.strings b/platform/darwin/resources/de.lproj/Foundation.strings
new file mode 100644
index 0000000000..e871efbf2f
--- /dev/null
+++ b/platform/darwin/resources/de.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@ Uhr";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@ Uhr";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "Osten";
+
+/* East, short */
+"COMPASS_E_SHORT" = "O";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "Ost zu Nord";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "OzN";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "Ost zu Süd";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "OzS";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "Ostnordost";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "ONO";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "Ostsüdost";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "OSO";
+
+/* North, long */
+"COMPASS_N_LONG" = "Nord";
+
+/* North, short */
+"COMPASS_N_SHORT" = "N";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "Nord zu Ost";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "NzO";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "Nord zu West";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "NzW";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "Nordost";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "NO";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "Nordost zu Ost";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "NOzO";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "Nordost zu Nord";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "NOzN";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "Nordnordost";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "NNO";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "Nordnordwest";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "NNW";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "Nordwest";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "NW";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "Nordwest zu Nord";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "NWzN";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "Nordwest zu West";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "NWzW";
+
+/* South, long */
+"COMPASS_S_LONG" = "Süd";
+
+/* South, short */
+"COMPASS_S_SHORT" = "S";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "Süd zu Ost";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "SzO";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "Süd zu West";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "SzW";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "Südost";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "SO";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "Südost zu Ost";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "SOzO";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "Südost zu Süd";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "SOzS";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "Südsüdost";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "SSO";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "Südsüdwest";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "SSW";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "Südwest";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "SW";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "Südwest zu Süd";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "SWzS";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "Südwest zu West";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "SWzW";
+
+/* West, long */
+"COMPASS_W_LONG" = "West";
+
+/* West, short */
+"COMPASS_W_SHORT" = "W";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "West zu Nord";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "WzN";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "West zu Süd";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "WzS";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "Westnordwest";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "WNW";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "Westsüdwest";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "WSW";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d Grad";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@ und %2$@";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@, %2$@ und %3$@";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@%2$@%3$@";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%2$@%3$@";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "%@ Ost";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "%@ Ost";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@O";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@ zu %2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@, %2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@, %2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d Minute(n)";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "%@ Nord";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "%@ Nord";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "%@ Süd";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "%@ Süd";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d Sekunde(n)";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "%@ West";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "%@ West";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@W";
+
diff --git a/platform/darwin/resources/de.lproj/Foundation.stringsdict b/platform/darwin/resources/de.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..776528a99c
--- /dev/null
+++ b/platform/darwin/resources/de.lproj/Foundation.stringsdict
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d Minute</string>
+ <key>other</key>
+ <string>%d Minuten</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d Sekunde</string>
+ <key>other</key>
+ <string>%d Sekunden</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/es.lproj/Foundation.stringsdict b/platform/darwin/resources/es.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..1c599f8bc1
--- /dev/null
+++ b/platform/darwin/resources/es.lproj/Foundation.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d grado</string>
+ <key>other</key>
+ <string>%d grados</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minuto</string>
+ <key>other</key>
+ <string>%d minutos</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d segundo</string>
+ <key>other</key>
+ <string>%d segundos</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/fr.lproj/Foundation.stringsdict b/platform/darwin/resources/fr.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..82cb954df6
--- /dev/null
+++ b/platform/darwin/resources/fr.lproj/Foundation.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d degré</string>
+ <key>other</key>
+ <string>%d degrés</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minute</string>
+ <key>other</key>
+ <string>%d minutes</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d seconde</string>
+ <key>other</key>
+ <string>%d secondes</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/ja.lproj/Foundation.strings b/platform/darwin/resources/ja.lproj/Foundation.strings
new file mode 100644
index 0000000000..b6dd83dac1
--- /dev/null
+++ b/platform/darwin/resources/ja.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@時方向";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@時方向";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "東";
+
+/* East, short */
+"COMPASS_E_SHORT" = "東";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "東微北";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "東微北";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "東微南";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "東微南";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "東北東";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "東北東";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "東南東";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "東南東";
+
+/* North, long */
+"COMPASS_N_LONG" = "北";
+
+/* North, short */
+"COMPASS_N_SHORT" = "北";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "北微東";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "北微東";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "北微西";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "北微西";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "東北";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "東北";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "東北微東";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "東北微東";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "東北微北";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "東北微北";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "北北東";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "北北東";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "北北西";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "北北西";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "西北";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "西北";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "西北微北";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "西北微北";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "西北微西";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "西北微西";
+
+/* South, long */
+"COMPASS_S_LONG" = "南";
+
+/* South, short */
+"COMPASS_S_SHORT" = "南";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "南微東";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "南微東";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "南微西";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "南微西";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "東南";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "東南";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "東南微東";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "東南微東";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "東南微南";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "東南微南";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "南南東";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "南南東";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "南南西";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "南南西";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "西南";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "西南";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "西南微南";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "西南微南";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "西南微西";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "西南微西";
+
+/* West, long */
+"COMPASS_W_LONG" = "西";
+
+/* West, short */
+"COMPASS_W_SHORT" = "西";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "西微北";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "西微北";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "西微南";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "西微南";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "西北西";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "西北西";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "西南西";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "西南西";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d度";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@度%2$@分";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@度%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%度2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%度2$@分%3$@秒";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "東%@";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "東%@";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@E";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@,%2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@,%2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@,%2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d分";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "北%@";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "北%@";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "南%@";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "南%@";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d秒";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "西%@";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "西%@";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@W";
+
diff --git a/platform/darwin/resources/pl.lproj/Foundation.stringsdict b/platform/darwin/resources/pl.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..016ba06b81
--- /dev/null
+++ b/platform/darwin/resources/pl.lproj/Foundation.stringsdict
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d stopień</string>
+ <key>few</key>
+ <string>%d stopnie</string>
+ <key>many</key>
+ <string>%d stopni</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minuta</string>
+ <key>few</key>
+ <string>%d minuty</string>
+ <key>many</key>
+ <string>%d minut</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d sekunda</string>
+ <key>few</key>
+ <string>%d sekundy</string>
+ <key>many</key>
+ <string>%d sekund</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/pt-BR.lproj/Foundation.stringsdict b/platform/darwin/resources/pt-BR.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..e99e86d98d
--- /dev/null
+++ b/platform/darwin/resources/pt-BR.lproj/Foundation.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d grau</string>
+ <key>other</key>
+ <string>%d graus</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minuto</string>
+ <key>other</key>
+ <string>%d minutos</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d segundo</string>
+ <key>other</key>
+ <string>%d segundos</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/ru.lproj/Foundation.stringsdict b/platform/darwin/resources/ru.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..b2d7467fd4
--- /dev/null
+++ b/platform/darwin/resources/ru.lproj/Foundation.stringsdict
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d градус</string>
+ <key>few</key>
+ <string>%d градуса</string>
+ <key>many</key>
+ <string>%d градусов</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d минута</string>
+ <key>few</key>
+ <string>%d минуты</string>
+ <key>many</key>
+ <string>%d минут</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d секунда</string>
+ <key>few</key>
+ <string>%d секунды</string>
+ <key>many</key>
+ <string>%d секунд</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/sv.lproj/Foundation.strings b/platform/darwin/resources/sv.lproj/Foundation.strings
new file mode 100644
index 0000000000..cac46cac1a
--- /dev/null
+++ b/platform/darwin/resources/sv.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "Öst";
+
+/* East, short */
+"COMPASS_E_SHORT" = "O";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "Ost till Nord";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "OtN";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "Ost till Syd";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "OtS";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "Ostnordost";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "ONO";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "Ostsydost";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "OSO";
+
+/* North, long */
+"COMPASS_N_LONG" = "Nord";
+
+/* North, short */
+"COMPASS_N_SHORT" = "N";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "Nord till Ost";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "NtO";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "Nord till Väst";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "NtV";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "Nordost";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "NO";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "Nordost till ost";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "NOtO";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "Nordost till nord";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "NOtN";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "Nordnordost";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "NNO";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "Nordnordväst";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "NNV";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "Nordväst";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "NV";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "Nordväst till nord";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "NVtN";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "Nordväst till väst";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "NVtV";
+
+/* South, long */
+"COMPASS_S_LONG" = "Syd";
+
+/* South, short */
+"COMPASS_S_SHORT" = "S";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "Syd till ost";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "StO";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "Syd till väst";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "StV";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "Sydost";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "SO";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "Sydost till ost";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "SOtO";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "Sydost till syd";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "SOtS";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "Sydsydost";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "SSO";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "Sydsydväst";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "SSV";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "Sydväst";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "SV";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "Sydväst till syd";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "SVtS";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "Sydväst till väst";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "SVtV";
+
+/* West, long */
+"COMPASS_W_LONG" = "Väst";
+
+/* West, short */
+"COMPASS_W_SHORT" = "V";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "Väst till nord";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "VtN";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "Väst till syd";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "VtS";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "Västnordväst";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "VNV";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "Västsydväst";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "VSV";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d grad(er)";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@ och %2$@";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@, %2$@ och %3$@";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@%2$@%3$@";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%2$@%3$@";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "%@ Öst";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "%@ Öst";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@O";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@ till %2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@, %2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@, %2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d minut(er)";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%dm";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%dm";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "%@ Nord";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "%@ Nord";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "%@ Syd";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "%@ Syd";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d sekund(er)";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%ds";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%ds";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "%@ Väst";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "%@ Väst";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@W";
+
diff --git a/platform/darwin/resources/sv.lproj/Foundation.stringsdict b/platform/darwin/resources/sv.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..e438ca02bf
--- /dev/null
+++ b/platform/darwin/resources/sv.lproj/Foundation.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d grad</string>
+ <key>other</key>
+ <string>%d grader</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minut</string>
+ <key>other</key>
+ <string>%d minuter</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d sekund</string>
+ <key>other</key>
+ <string>%d sekunder</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/uk.lproj/Foundation.stringsdict b/platform/darwin/resources/uk.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..76dbbfc5e9
--- /dev/null
+++ b/platform/darwin/resources/uk.lproj/Foundation.stringsdict
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d градус</string>
+ <key>few</key>
+ <string>%d градуси</string>
+ <key>many</key>
+ <string>%d градусів</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d хвилина</string>
+ <key>few</key>
+ <string>%d хвилини</string>
+ <key>many</key>
+ <string>%d хвилин</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d секунда</string>
+ <key>few</key>
+ <string>%d секунди</string>
+ <key>many</key>
+ <string>%d секунд</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/vi.lproj/Foundation.strings b/platform/darwin/resources/vi.lproj/Foundation.strings
new file mode 100644
index 0000000000..f29f8e8730
--- /dev/null
+++ b/platform/darwin/resources/vi.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@ giờ";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@ giờ";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "đông";
+
+/* East, short */
+"COMPASS_E_SHORT" = "Đ";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "đông về bắc";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "ĐvB";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "đông về nam";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "ĐvN";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "đông đông bắc";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "ĐĐB";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "đông đông nam";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "ĐĐN";
+
+/* North, long */
+"COMPASS_N_LONG" = "bắc";
+
+/* North, short */
+"COMPASS_N_SHORT" = "B";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "bắc về đông";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "BvĐ";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "bắc về tây";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "BvT";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "đông bắc";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "ĐB";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "đông bắc về đông";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "ĐBvĐ";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "đông bắc về bắc";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "ĐBvB";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "bắc đông bắc";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "BĐB";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "bắc tây bắc";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "BTB";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "tây bắc";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "TB";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "tây bắc về bắc";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "TBvB";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "tây bắc về tây";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "TBvT";
+
+/* South, long */
+"COMPASS_S_LONG" = "nam";
+
+/* South, short */
+"COMPASS_S_SHORT" = "N";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "nam về đông";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "NvĐ";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "nam về tây";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "NvT";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "đông nam";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "ĐN";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "đông nam về đông";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "ĐNvĐ";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "đông nam về nam";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "ĐNvN";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "nam đông nam";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "NĐN";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "nam tây nam";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "NTN";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "tây nam";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "TN";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "tây nam về nam";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "TNvN";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "tây nam về tây";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "TNvT";
+
+/* West, long */
+"COMPASS_W_LONG" = "tây";
+
+/* West, short */
+"COMPASS_W_SHORT" = "T";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "tây về bắc";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "TvB";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "tây về nam";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "TvN";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "tây tây bắc";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "TTB";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "tây tây nam";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "TTN";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d độ";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@ %2$@";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@, %2$@, %3$@";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@%2$@%3$@";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%2$@%3$@";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "%@ kinh độ đông";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "%@ đông";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@Đ";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@ và %2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@, %2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@, %2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d phút";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "%@ vĩ độ bắc";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "%@ bắc";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "%@ vĩ độ nam";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "%@ nam";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@N";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d giây";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "%@ kinh độ tây";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "%@ tây";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@T";
+
diff --git a/platform/darwin/resources/zh-Hans.lproj/Foundation.strings b/platform/darwin/resources/zh-Hans.lproj/Foundation.strings
new file mode 100644
index 0000000000..7dec6184e5
--- /dev/null
+++ b/platform/darwin/resources/zh-Hans.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@点";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@点";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "东";
+
+/* East, short */
+"COMPASS_E_SHORT" = "东";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "东微北";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "东微北";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "东微南";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "东微南";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "东北偏东";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "东北偏东";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "东南偏东";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "东南偏东";
+
+/* North, long */
+"COMPASS_N_LONG" = "北";
+
+/* North, short */
+"COMPASS_N_SHORT" = "北";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "北微东";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "北微东";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "北微西";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "北微西";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "东北";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "东北";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "东北微东";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "东北微东";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "东北微北";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "东北微北";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "东北偏北";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "东北偏北";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "西北偏北";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "西北偏北";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "西北";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "西北";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "西北微北";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "西北微北";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "西北微西";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "西北微西";
+
+/* South, long */
+"COMPASS_S_LONG" = "南";
+
+/* South, short */
+"COMPASS_S_SHORT" = "南";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "南微东";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "南微东";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "南微西";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "南微西";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "东南";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "东南";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "东南微东";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "东南微东";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "东南微南";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "东南微南";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "东南偏南";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "东南偏南";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "西南偏南";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "西南偏南";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "西南";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "西南";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "西南偏南";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "西南偏南";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "西南偏西";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "西南偏西";
+
+/* West, long */
+"COMPASS_W_LONG" = "西";
+
+/* West, short */
+"COMPASS_W_SHORT" = "西";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "西微北";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "西微北";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "西微南";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "西微南";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "西北偏西";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "西北偏西";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "西南偏西";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "西南偏西";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d度";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@度%2$@分";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@度%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%度2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%度2$@分%3$@秒";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "东经%@";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "东经%@";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@E";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@,%2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@,%2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@,%2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d分";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "北纬%@";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "北纬%@";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "南纬%@";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "南纬%@";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d秒";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "西经%@";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "西经%@";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@W";
+
diff --git a/platform/darwin/resources/zh-Hant.lproj/Foundation.strings b/platform/darwin/resources/zh-Hant.lproj/Foundation.strings
new file mode 100644
index 0000000000..41b1d2baae
--- /dev/null
+++ b/platform/darwin/resources/zh-Hant.lproj/Foundation.strings
@@ -0,0 +1,291 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@點";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@點";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "東";
+
+/* East, short */
+"COMPASS_E_SHORT" = "東";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "東微北";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "東微北";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "東微南";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "東微南";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "東北偏東";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "東北偏東";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "東南偏東";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "東南偏東";
+
+/* North, long */
+"COMPASS_N_LONG" = "北";
+
+/* North, short */
+"COMPASS_N_SHORT" = "北";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "北微東";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "北微東";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "北微西";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "北微西";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "東北";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "東北";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "東北微東";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "東北微東";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "東北微北";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "東北微北";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "東北偏北";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "東北偏北";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "西北偏北";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "西北偏北";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "西北";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "西北";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "西北微北";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "西北微北";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "西北微西";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "西北微西";
+
+/* South, long */
+"COMPASS_S_LONG" = "南";
+
+/* South, short */
+"COMPASS_S_SHORT" = "南";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "南微東";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "南微東";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "南微西";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "南微西";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "東南";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "東南";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "東南微東";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "東南微東";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "東南微南";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "東南微南";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "東南偏南";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "東南偏南";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "西南偏南";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "西南偏南";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "西南";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "西南";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "西南偏南";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "西南偏南";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "西南偏西";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "西南偏西";
+
+/* West, long */
+"COMPASS_W_LONG" = "西";
+
+/* West, short */
+"COMPASS_W_SHORT" = "西";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "西微北";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "西微北";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "西微南";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "西微南";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "西北偏西";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "西北偏西";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "西南偏西";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "西南偏西";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d度";
+
+/* Degrees format, medium: {degrees} */
+"COORD_DEG_MEDIUM" = "%d°";
+
+/* Degrees format, short: {degrees} */
+"COORD_DEG_SHORT" = "%d°";
+
+/* Coordinate format, long: {degrees}{minutes} */
+"COORD_DM_LONG" = "%1$@度%2$@分";
+
+/* Coordinate format, medium: {degrees}{minutes} */
+"COORD_DM_MEDIUM" = "%1$@度%2$@";
+
+/* Coordinate format, short: {degrees}{minutes} */
+"COORD_DM_SHORT" = "%1$@%度2$@";
+
+/* Coordinate format, long: {degrees}{minutes}{seconds} */
+"COORD_DMS_LONG" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, medium: {degrees}{minutes}{seconds} */
+"COORD_DMS_MEDIUM" = "%1$@度%2$@分%3$@秒";
+
+/* Coordinate format, short: {degrees}{minutes}{seconds} */
+"COORD_DMS_SHORT" = "%1$@%度2$@分%3$@秒";
+
+/* East longitude format, long: {longitude} */
+"COORD_E_LONG" = "東經%@";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "東經%@";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@E";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@,%2$@";
+
+/* Coordinate pair format, medium: {latitude}, {longitude} */
+"COORD_FMT_MEDIUM" = "%1$@,%2$@";
+
+/* Coordinate pair format, short: {latitude}, {longitude} */
+"COORD_FMT_SHORT" = "%1$@,%2$@";
+
+/* Minutes format, long */
+"COORD_MIN_LONG" = "%d分";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "北緯%@";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "北緯%@";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "南緯%@";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "南緯%@";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d秒";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "西經%@";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "西經%@";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@W";
+
diff --git a/platform/darwin/scripts/check-public-symbols.js b/platform/darwin/scripts/check-public-symbols.js
new file mode 100755
index 0000000000..4dde5d677b
--- /dev/null
+++ b/platform/darwin/scripts/check-public-symbols.js
@@ -0,0 +1,83 @@
+#!/usr/bin/env node
+
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const execFileSync = require('child_process').execFileSync;
+const _ = require('lodash');
+
+const keyword = /\bMGL_EXPORT\b/;
+
+let scanned = [];
+
+function hasMissingSymbols(os) {
+ let missing = false;
+ let sdk = os === 'iOS' ? 'iphonesimulator' : 'macosx';
+ let sysroot = execFileSync('xcrun', ['--show-sdk-path', '--sdk', sdk]).toString().trim();
+ let umbrellaPath = `platform/${os.toLowerCase()}/src/Mapbox.h`;
+ let docArgs = ['doc', '--objc', umbrellaPath, '--',
+ '-x', 'objective-c', '-I', 'platform/darwin/src/', '-isysroot', sysroot];
+ let docStr = execFileSync('sourcekitten', docArgs).toString().trim();
+ let docJson = JSON.parse(docStr);
+ _.forEach(docJson, function (result) {
+ _.forEach(result, function (structure, path) {
+ // Prevent multiple scans of the same file.
+ if (scanned.indexOf(path) >= 0) return;
+ scanned.push(path);
+
+ const src = fs.readFileSync(path, 'utf8').split('\n');
+ _.forEach(structure['key.substructure'], function (substructure) {
+ switch (substructure['key.kind']) {
+ case 'sourcekitten.source.lang.objc.decl.class':
+ if (!(keyword.test(src[substructure['key.doc.line'] - 1]) || keyword.test(src[substructure['key.doc.line'] - 2]))) {
+ console.warn(`- missing symbol export for class ${substructure['key.name']} in ${path}:${substructure['key.doc.line']}:${substructure['key.doc.column']}`);
+ missing = true;
+ }
+ break;
+ case 'sourcekitten.source.lang.objc.decl.constant':
+ if (!keyword.test(src[substructure['key.doc.line'] - 1])) {
+ console.warn(`- missing symbol export for constant ${substructure['key.name']} in ${path}:${substructure['key.doc.line']}:${substructure['key.doc.column']}`);
+ missing = true;
+ }
+ break;
+ }
+ });
+ });
+ });
+
+ return missing;
+}
+
+function ensureSourceKittenIsInstalled() {
+ try {
+ execFileSync('which', ['sourcekitten']);
+ } catch (e) {
+ console.log(`Installing SourceKitten via Homebrew…`);
+ execFileSync('brew', ['install', 'sourcekitten']);
+ }
+}
+
+if (process.argv.length < 3) {
+ console.warn(`Usage: ${path.relative(process.cwd(), process.argv[1])} [macOS|iOS] ...`);
+ process.exit(1);
+}
+
+ensureSourceKittenIsInstalled();
+
+let missing = false;
+for (var i = 2; i < process.argv.length; i++) {
+ let os = process.argv[i];
+ if (os == 'iOS' || os == 'macOS') {
+ missing |= hasMissingSymbols(os);
+ } else {
+ console.warn(`Argument must be one of iOS or macOS`);
+ process.exit(1);
+ }
+}
+
+if (missing) {
+ process.exit(1);
+} else {
+ console.warn(`All symbols are correctly exported.`);
+}
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 0266e25890..cacca57700 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -4,11 +4,20 @@ const fs = require('fs');
const ejs = require('ejs');
const _ = require('lodash');
const colorParser = require('csscolorparser');
+
+require('../../../scripts/style-code');
+
const cocoaConventions = require('./style-spec-cocoa-conventions-v8.json');
-let spec = _.merge(require('mapbox-gl-style-spec').latest, require('./style-spec-overrides-v8.json'));
const prefix = 'MGL';
const suffix = 'StyleLayer';
+let spec = _.merge(require('../../../mapbox-gl-js/src/style-spec/reference/v8'), require('./style-spec-overrides-v8.json'));
+
+///
+// Temporarily IGNORE layers that are in the spec yet still not supported in mbgl core
+///
+delete spec.layer.type.values['fill-extrusion'];
+
// Rename properties and keep `original` for use with setters and getters
_.forOwn(cocoaConventions, function (properties, kind) {
_.forOwn(properties, function (newName, oldName) {
@@ -22,7 +31,7 @@ _.forOwn(cocoaConventions, function (properties, kind) {
}
delete spec[kind][oldName];
spec[kind][newName] = property;
-
+
// Update requirements in other properties.
let updateRequirements = function (property, name) {
let requires = property.requires || [];
@@ -148,7 +157,7 @@ global.mbglTestValue = function (property, layerType) {
return `mbgl::style::${type}Type::${value}`;
}
case 'color':
- return '{ .r = 1, .g = 0, .b = 0, .a = 1 }';
+ return '{ 1, 0, 0, 1 }';
case 'array':
switch (arrayType(property)) {
case 'dasharray':
@@ -216,7 +225,7 @@ global.testHelperMessage = function (property, layerType, isFunction) {
};
global.propertyDoc = function (propertyName, property, layerType, kind) {
- // Match references to other property names & values.
+ // Match references to other property names & values.
// Requires the format 'When `foo` is set to `bar`,'.
let doc = property.doc.replace(/`([^`]+?)` is set to `([^`]+?)`/g, function (m, peerPropertyName, propertyValue, offset, str) {
let otherProperty = camelizeWithLeadingLowercase(peerPropertyName);
@@ -271,6 +280,30 @@ global.propertyDoc = function (propertyName, property, layerType, kind) {
}
doc += `\n\nThis attribute corresponds to the <a href="https://www.mapbox.com/mapbox-gl-style-spec/#${anchor}"><code>${property.original}</code></a> layout property in the Mapbox Style Specification.`;
}
+ doc += '\n\nYou can set this property to an instance of:\n\n' +
+ '* `MGLStyleConstantValue`\n';
+ if (property["property-function"]) {
+ doc += '* `MGLCameraStyleFunction` with an interpolation mode of:\n' +
+ ' * `MGLInterpolationModeExponential`\n' +
+ ' * `MGLInterpolationModeInterval`\n' +
+ '* `MGLSourceStyleFunction` with an interpolation mode of:\n' +
+ ' * `MGLInterpolationModeExponential`\n' +
+ ' * `MGLInterpolationModeInterval`\n' +
+ ' * `MGLInterpolationModeCategorical`\n' +
+ ' * `MGLInterpolationModeIdentity`\n' +
+ '* `MGLCompositeStyleFunction` with an interpolation mode of:\n' +
+ ' * `MGLInterpolationModeExponential`\n' +
+ ' * `MGLInterpolationModeInterval`\n' +
+ ' * `MGLInterpolationModeCategorical`\n';
+ } else {
+ if (property.function === "interpolated") {
+ doc += '* `MGLCameraStyleFunction` with an interpolation mode of:\n' +
+ ' * `MGLInterpolationModeExponential`\n' +
+ ' * `MGLInterpolationModeInterval`\n';
+ } else {
+ doc += '* `MGLCameraStyleFunction` with an interpolation mode of `MGLInterpolationModeInterval`\n';
+ }
+ }
}
return doc;
};
@@ -401,6 +434,13 @@ global.propertyType = function (property) {
}
};
+global.isInterpolatable = function (property) {
+ const type = property.type === 'array' ? property.value : property.type;
+ return type !== 'boolean' &&
+ type !== 'enum' &&
+ type !== 'string';
+};
+
global.valueTransformerArguments = function (property) {
let objCType = propertyType(property);
switch (property.type) {
@@ -411,7 +451,7 @@ global.valueTransformerArguments = function (property) {
case 'string':
return ['std::string', objCType];
case 'enum':
- return [`mbgl::style::${mbglType(property)}`, objCType];
+ return [mbglType(property), 'NSValue *', mbglType(property), `MGL${camelize(property.name)}`];
case 'color':
return ['mbgl::Color', objCType];
case 'array':
@@ -552,7 +592,7 @@ for (var layer of layers) {
if (enumProperties.length) {
layer.enumProperties = enumProperties;
}
-
+
let renamedProperties = {};
_.assign(renamedProperties, _.filter(layer.properties, prop => 'original' in prop || 'getter' in prop));
if (!_.isEmpty(renamedProperties)) {
diff --git a/platform/darwin/scripts/update-examples.js b/platform/darwin/scripts/update-examples.js
index e6b747a460..404cda102a 100644
--- a/platform/darwin/scripts/update-examples.js
+++ b/platform/darwin/scripts/update-examples.js
@@ -10,9 +10,9 @@ const examplesSrc = fs.readFileSync('platform/darwin/test/MGLDocumentationExampl
// /** Front matter to describe the example. **/
// func testMGLClass$member() {
// ...
-// //#-example-code
+// // #-example-code
// let sampleCode: String?
-// //#-end-example-code
+// // #-end-example-code
// ...
// }
//
@@ -35,16 +35,16 @@ function completeSymbolInSource(src, line, exampleCode) {
// Split the file contents right before the symbol declaration (but after its documentation comment).
let srcUpToSymbol = src.split('\n', line - 1).join('\n');
let srcFromSymbol = src.substr(srcUpToSymbol.length);
-
+
// Match the documentation comment block that is not followed by the beginning or end of a declaration.
let commentMatch = srcUpToSymbol.match(/\/\*\*\s*(?:[^*]|\*(?!\/))+?\s*\*\/[^;{}]*?$/);
-
+
// Replace the Swift code block with the test method’s contents.
let completedComment = commentMatch[0].replace(/^([ \t]*)```swift\n[^]*?```/m, function (m, indentation) {
// Apply the original indentation to each line.
return ('```swift\n' + exampleCode + '\n```').replace(/^/gm, indentation);
});
-
+
// Splice the modified comment into the overall file contents.
srcUpToSymbol = (srcUpToSymbol.substr(0, commentMatch.index) + completedComment +
srcUpToSymbol.substr(commentMatch.index + commentMatch[0].length));
@@ -60,13 +60,13 @@ while ((match = exampleRegex.exec(examplesSrc)) !== null) {
// Trim leading whitespace from the example code.
exampleCode = exampleCode.replace(new RegExp('^' + indentation, 'gm'), '');
-
+
examples[testMethodName] = exampleCode;
}
function completeExamples(os) {
console.log(`Installing ${os} SDK examples…`);
-
+
let sdk = os === 'iOS' ? 'iphonesimulator' : 'macosx';
let sysroot = execFileSync('xcrun', ['--show-sdk-path', '--sdk', sdk]).toString().trim();
let umbrellaPath = `platform/${os.toLowerCase()}/src/Mapbox.h`;
@@ -88,17 +88,17 @@ function completeExamples(os) {
_.forEachRight(substructure['key.substructure'], function (substructure, idx, substructures) {
completeSubstructure(substructure, idx, substructures, _.concat(symbolPath, substructure['key.name']));
});
-
+
let comment = substructure['key.doc.comment'];
if (!comment || !comment.match(/^(?:\s*)```swift\n/m)) {
return;
}
-
+
// Lazily read in the existing file.
if (!src) {
newSrc = src = fs.readFileSync(path, 'utf8');
}
-
+
// Get the contents of the test method whose name matches the symbol path.
let testMethodName = symbolPath.join('$').replace(/\$[+-]/, '$').replace(/:/g, '_');
let example = examples[testMethodName];
@@ -106,23 +106,23 @@ function completeExamples(os) {
console.error(`MGLDocumentationExampleTests.${testMethodName}() not found.`);
process.exit(1);
}
-
+
// Resolve conditional compilation blocks.
example = example.replace(/^(\s*)#if\s+os\((iOS|macOS)\)\n([^]*?)(?:^\1#else\n([^]*?))?^\1#endif\b\n?/gm,
function (m, indentation, ifOs, ifCase, elseCase) {
return (os === ifOs ? ifCase : elseCase).replace(new RegExp('^ ', 'gm'), '');
}).replace(/\n$/, '');
-
+
// Insert the test method contents into the documentation comment just
// above the substructure.
let startLine = substructure['key.parsed_scope.start'];
newSrc = completeSymbolInSource(newSrc, startLine, example);
});
-
+
if (!src) {
return;
}
-
+
// Write out the modified file contents.
if (src === newSrc) {
console.log('Skipping', path);
diff --git a/platform/darwin/src/MGLAccountManager.h b/platform/darwin/src/MGLAccountManager.h
index fe602aa210..741cc323cb 100644
--- a/platform/darwin/src/MGLAccountManager.h
+++ b/platform/darwin/src/MGLAccountManager.h
@@ -1,11 +1,14 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
The MGLAccountManager object provides a global way to set a Mapbox API access
token.
*/
+MGL_EXPORT
@interface MGLAccountManager : NSObject
#pragma mark Authorizing Access
@@ -14,17 +17,17 @@ NS_ASSUME_NONNULL_BEGIN
Set the
<a href="https://www.mapbox.com/help/define-access-token/">Mapbox access token</a>
to be used by all instances of MGLMapView in the current application.
-
+
Mapbox-hosted vector tiles and styles require an API access token, which you
can obtain from the
<a href="https://www.mapbox.com/studio/account/tokens/">Mapbox account page</a>.
Access tokens associate requests to Mapbox’s vector tile and style APIs with
your Mapbox account. They also deter other developers from using your styles
without your permission.
-
+
@param accessToken A Mapbox access token. Calling this method with a value of
`nil` has no effect.
-
+
@note You must set the access token before attempting to load any Mapbox-hosted
style. Therefore, you should generally set it before creating an instance of
MGLMapView. The recommended way to set an access token is to add an entry to
diff --git a/platform/darwin/src/MGLAccountManager.m b/platform/darwin/src/MGLAccountManager.m
index 31baf4e249..0f5d033031 100644
--- a/platform/darwin/src/MGLAccountManager.m
+++ b/platform/darwin/src/MGLAccountManager.m
@@ -65,7 +65,7 @@
if (!accessToken.length) {
return;
}
-
+
[MGLAccountManager sharedManager].accessToken = accessToken;
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
diff --git a/platform/darwin/src/MGLAnnotation.h b/platform/darwin/src/MGLAnnotation.h
index 4c8f600240..a0a58e83a6 100644
--- a/platform/darwin/src/MGLAnnotation.h
+++ b/platform/darwin/src/MGLAnnotation.h
@@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
the visual representation of the annotation but typically coordinate (in
conjunction with the map view’s delegate) the creation of an appropriate
objects to handle the display.
-
+
An object that adopts this protocol must implement the `coordinate` property.
The other methods of this protocol are optional.
*/
@@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
The string containing the annotation’s title.
-
+
Although this property is optional, if you support the selection of annotations
in your map view, you are expected to provide this property. This string is
displayed in the callout for the associated annotation.
@@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
The string containing the annotation’s subtitle.
-
+
This string is displayed in the callout for the associated annotation.
*/
@property (nonatomic, readonly, copy, nullable) NSString *subtitle;
diff --git a/platform/darwin/src/MGLAttributionInfo.h b/platform/darwin/src/MGLAttributionInfo.h
index 3c9df47912..031a10060f 100644
--- a/platform/darwin/src/MGLAttributionInfo.h
+++ b/platform/darwin/src/MGLAttributionInfo.h
@@ -2,6 +2,7 @@
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@@ -10,11 +11,12 @@ NS_ASSUME_NONNULL_BEGIN
Information about an attribution statement, usually a copyright or trademark
statement, associated with a map content source.
*/
+MGL_EXPORT
@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.
@@ -28,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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.
@@ -38,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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.
*/
@@ -47,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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 the `MGLMapView.zoomLevel` property
for more information.
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm
index 2546808b34..fa2ae787a5 100644
--- a/platform/darwin/src/MGLAttributionInfo.mm
+++ b/platform/darwin/src/MGLAttributionInfo.mm
@@ -18,7 +18,7 @@
if (!htmlString) {
return @[];
}
-
+
NSDictionary *options = @{
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding),
@@ -56,7 +56,7 @@
}
NSString *styledHTML = [NSString stringWithFormat:@"<style type='text/css'>%@</style>%@", css, htmlString];
NSData *htmlData = [styledHTML dataUsingEncoding:NSUTF8StringEncoding];
-
+
#if TARGET_OS_IPHONE
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:htmlData
options:options
@@ -67,7 +67,7 @@
options:options
documentAttributes:nil];
#endif
-
+
NSMutableArray *infos = [NSMutableArray array];
[attributedString enumerateAttribute:NSLinkAttributeName
inRange:attributedString.mgl_wholeRange
@@ -75,7 +75,7 @@
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
@@ -85,14 +85,14 @@
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];
@@ -124,7 +124,7 @@
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)];
@@ -142,7 +142,7 @@
/**
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.
@@ -179,14 +179,14 @@
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;
}
diff --git a/platform/darwin/src/MGLAttributionInfo_Private.h b/platform/darwin/src/MGLAttributionInfo_Private.h
index c9a428b571..4b28fa5266 100644
--- a/platform/darwin/src/MGLAttributionInfo_Private.h
+++ b/platform/darwin/src/MGLAttributionInfo_Private.h
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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.
@@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
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.
*/
@@ -38,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN
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;
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.h b/platform/darwin/src/MGLBackgroundStyleLayer.h
index ed797c9f0a..c6fd6113cb 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.h
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.h
@@ -1,6 +1,7 @@
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLStyleLayer.h"
@@ -20,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
If the background style layer is transparent or omitted from the style, any
portion of the map view that does not show another style layer is transparent.
*/
+MGL_EXPORT
@interface MGLBackgroundStyleLayer : MGLStyleLayer
- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER;
@@ -36,6 +38,13 @@ NS_ASSUME_NONNULL_BEGIN
This property is only applied to the style if `backgroundPattern` is set to
`nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *backgroundColor;
#else
@@ -48,6 +57,13 @@ NS_ASSUME_NONNULL_BEGIN
This property is only applied to the style if `backgroundPattern` is set to
`nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *backgroundColor;
#endif
@@ -58,6 +74,13 @@ NS_ASSUME_NONNULL_BEGIN
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `1`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *backgroundOpacity;
@@ -65,6 +88,12 @@ NS_ASSUME_NONNULL_BEGIN
Name of image in style images to use for drawing an image background. For
seamless patterns, image width and height must be a factor of two (2, 4, 8,
..., 512).
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *backgroundPattern;
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm
index f6a00de941..166c5926f5 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.mm
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,6 +8,7 @@
#import "MGLStyleValue_Private.h"
#import "MGLBackgroundStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/background_layer.hpp>
@interface MGLBackgroundStyleLayer ()
@@ -85,28 +86,34 @@
- (void)setBackgroundColor:(MGLStyleValue<MGLColor *> *)backgroundColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(backgroundColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(backgroundColor);
self.rawLayer->setBackgroundColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)backgroundColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getBackgroundColor() ?: self.rawLayer->getDefaultBackgroundColor();
+ auto propertyValue = self.rawLayer->getBackgroundColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultBackgroundColor());
+ }
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setBackgroundOpacity:(MGLStyleValue<NSNumber *> *)backgroundOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(backgroundOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(backgroundOpacity);
self.rawLayer->setBackgroundOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)backgroundOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getBackgroundOpacity() ?: self.rawLayer->getDefaultBackgroundOpacity();
+ auto propertyValue = self.rawLayer->getBackgroundOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultBackgroundOpacity());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -120,7 +127,10 @@
- (MGLStyleValue<NSString *> *)backgroundPattern {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getBackgroundPattern() ?: self.rawLayer->getDefaultBackgroundPattern();
+ auto propertyValue = self.rawLayer->getBackgroundPattern();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultBackgroundPattern());
+ }
return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h
index 1117077d59..b3e9ee7161 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.h
+++ b/platform/darwin/src/MGLCircleStyleLayer.h
@@ -1,6 +1,7 @@
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -8,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Controls the scaling behavior of the circle when the map is pitched.
-
+
Values of this type are used in the `MGLCircleStyleLayer.circleScaleAlignment`
property.
*/
@@ -25,7 +26,7 @@ typedef NS_ENUM(NSUInteger, MGLCircleScaleAlignment) {
/**
Controls the translation reference point.
-
+
Values of this type are used in the `MGLCircleStyleLayer.circleTranslationAnchor`
property.
*/
@@ -53,28 +54,29 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
To display circles on the map whose radii correspond to real-world distances,
use many-sided regular polygons and configure their appearance using an
`MGLFillStyleLayer` object.
-
+
You can access an existing circle style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new circle style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
### Example
-
+
```swift
let layer = MGLCircleStyleLayer(identifier: "circles", source: population)
layer.sourceLayerIdentifier = "population"
layer.circleColor = MGLStyleValue(rawValue: .green)
- layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [
- 12: MGLStyleValue(rawValue: 2),
- 22: MGLStyleValue(rawValue: 180)
- ])
+ layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: [12: MGLStyleValue(rawValue: 2),
+ 22: MGLStyleValue(rawValue: 180)],
+ options: [.interpolationBase: 1.75])
layer.circleOpacity = MGLStyleValue(rawValue: 0.7)
layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married")
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLCircleStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Paint Attributes
@@ -86,6 +88,22 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `0`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleBlur;
@@ -96,6 +114,22 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
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.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *circleColor;
#else
@@ -105,6 +139,22 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
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.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *circleColor;
#endif
@@ -115,6 +165,22 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `1`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleOpacity;
@@ -126,6 +192,22 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `5`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleRadius;
@@ -139,6 +221,12 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-circle-pitch-scale"><code>circle-pitch-scale</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circleScaleAlignment;
@@ -146,6 +234,111 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
#if TARGET_OS_IPHONE
/**
+ The stroke color of the circle.
+
+ 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.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *circleStrokeColor;
+#else
+/**
+ The stroke color of the circle.
+
+ 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.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *circleStrokeColor;
+#endif
+
+/**
+ The opacity of the circle's stroke.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `1`. Set this property to `nil` to reset
+ it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleStrokeOpacity;
+
+/**
+ The width of the circle's stroke. Strokes are placed outside of the
+ `circleRadius`.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `0`. Set this property to `nil` to reset
+ it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleStrokeWidth;
+
+#if TARGET_OS_IPHONE
+/**
The geometry's offset.
This property is measured in points.
@@ -157,6 +350,13 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-circle-translate"><code>circle-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circleTranslation;
#else
@@ -172,6 +372,13 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-circle-translate"><code>circle-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circleTranslation;
#endif
@@ -191,6 +398,12 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-circle-translate-anchor"><code>circle-translate-anchor</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circleTranslationAnchor;
diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm
index 0aff74ffa6..fc8e3a40c7 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.mm
+++ b/platform/darwin/src/MGLCircleStyleLayer.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLCircleStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLCircleScaleAlignment, {
@@ -57,7 +59,7 @@ namespace mbgl {
- (NSString *)sourceIdentifier
{
MGLAssertStyleLayerIsValid();
-
+
return @(self.rawLayer->getSourceID().c_str());
}
@@ -134,57 +136,69 @@ namespace mbgl {
- (void)setCircleBlur:(MGLStyleValue<NSNumber *> *)circleBlur {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleBlur);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(circleBlur);
self.rawLayer->setCircleBlur(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)circleBlur {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCircleBlur() ?: self.rawLayer->getDefaultCircleBlur();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getCircleBlur();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleBlur());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setCircleColor:(MGLStyleValue<MGLColor *> *)circleColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(circleColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(circleColor);
self.rawLayer->setCircleColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)circleColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCircleColor() ?: self.rawLayer->getDefaultCircleColor();
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getCircleColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleColor());
+ }
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setCircleOpacity:(MGLStyleValue<NSNumber *> *)circleOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(circleOpacity);
self.rawLayer->setCircleOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)circleOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCircleOpacity() ?: self.rawLayer->getDefaultCircleOpacity();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getCircleOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleOpacity());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setCircleRadius:(MGLStyleValue<NSNumber *> *)circleRadius {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleRadius);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(circleRadius);
self.rawLayer->setCircleRadius(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)circleRadius {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCircleRadius() ?: self.rawLayer->getDefaultCircleRadius();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getCircleRadius();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleRadius());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setCircleScaleAlignment:(MGLStyleValue<NSValue *> *)circleScaleAlignment {
@@ -197,7 +211,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)circleScaleAlignment {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCirclePitchScale() ?: self.rawLayer->getDefaultCirclePitchScale();
+ auto propertyValue = self.rawLayer->getCirclePitchScale();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::CirclePitchScaleType, NSValue *, mbgl::style::CirclePitchScaleType, MGLCircleScaleAlignment>().toEnumStyleValue(self.rawLayer->getDefaultCirclePitchScale());
+ }
return MGLStyleValueTransformer<mbgl::style::CirclePitchScaleType, NSValue *, mbgl::style::CirclePitchScaleType, MGLCircleScaleAlignment>().toEnumStyleValue(propertyValue);
}
@@ -208,17 +225,71 @@ namespace mbgl {
return self.circleScaleAlignment;
}
+- (void)setCircleStrokeColor:(MGLStyleValue<MGLColor *> *)circleStrokeColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(circleStrokeColor);
+ self.rawLayer->setCircleStrokeColor(mbglValue);
+}
+
+- (MGLStyleValue<MGLColor *> *)circleStrokeColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCircleStrokeColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleStrokeColor());
+ }
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
+}
+
+- (void)setCircleStrokeOpacity:(MGLStyleValue<NSNumber *> *)circleStrokeOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(circleStrokeOpacity);
+ self.rawLayer->setCircleStrokeOpacity(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)circleStrokeOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCircleStrokeOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleStrokeOpacity());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
+}
+
+- (void)setCircleStrokeWidth:(MGLStyleValue<NSNumber *> *)circleStrokeWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(circleStrokeWidth);
+ self.rawLayer->setCircleStrokeWidth(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)circleStrokeWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCircleStrokeWidth();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultCircleStrokeWidth());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
+}
+
- (void)setCircleTranslation:(MGLStyleValue<NSValue *> *)circleTranslation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(circleTranslation);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(circleTranslation);
self.rawLayer->setCircleTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)circleTranslation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCircleTranslate() ?: self.rawLayer->getDefaultCircleTranslate();
+ auto propertyValue = self.rawLayer->getCircleTranslate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultCircleTranslate());
+ }
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
@@ -239,7 +310,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)circleTranslationAnchor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getCircleTranslateAnchor() ?: self.rawLayer->getDefaultCircleTranslateAnchor();
+ auto propertyValue = self.rawLayer->getCircleTranslateAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLCircleTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultCircleTranslateAnchor());
+ }
return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLCircleTranslationAnchor>().toEnumStyleValue(propertyValue);
}
diff --git a/platform/darwin/src/MGLClockDirectionFormatter.h b/platform/darwin/src/MGLClockDirectionFormatter.h
index ea427aa7b1..86a9452846 100644
--- a/platform/darwin/src/MGLClockDirectionFormatter.h
+++ b/platform/darwin/src/MGLClockDirectionFormatter.h
@@ -1,6 +1,8 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -8,24 +10,25 @@ NS_ASSUME_NONNULL_BEGIN
of headings relative to the user, known as <i>clock positions</i>. For
example, a value of `90` may be formatted as “3 o’clock”, depending on the
locale.
-
+
Use this class to create localized heading strings when displaying directions
relative to the user’s current location and heading. To format a direction
irrespective of the user’s orientation, use `MGLCompassDirectionFormatter`
instead.
*/
+MGL_EXPORT
@interface MGLClockDirectionFormatter : NSFormatter
/**
The unit style used by this formatter.
-
+
This property defaults to `NSFormattingUnitStyleMedium`.
*/
@property (nonatomic) NSFormattingUnitStyle unitStyle;
/**
Returns a clock position string for the provided value.
-
+
@param direction The heading, measured in degrees, where 0° means “straight
ahead” and 90° means “directly to your right”.
@return The clock position string appropriately formatted for the receiver’s
diff --git a/platform/darwin/src/MGLClockDirectionFormatter.m b/platform/darwin/src/MGLClockDirectionFormatter.m
index fd67968e65..62a0ea995d 100644
--- a/platform/darwin/src/MGLClockDirectionFormatter.m
+++ b/platform/darwin/src/MGLClockDirectionFormatter.m
@@ -28,16 +28,16 @@
case NSFormattingUnitStyleShort:
format = NSLocalizedStringWithDefaultValue(@"CLOCK_FMT_SHORT", @"Foundation", nil, @"%@:00", @"Clock position format, short: {hours}:00");
break;
-
+
case NSFormattingUnitStyleMedium:
format = NSLocalizedStringWithDefaultValue(@"CLOCK_FMT_MEDIUM", @"Foundation", nil, @"%@ o’clock", @"Clock position format, medium: {hours} o’clock");
-
+
break;
-
+
case NSFormattingUnitStyleLong:
format = NSLocalizedStringWithDefaultValue(@"CLOCK_FMT_LONG", @"Foundation", nil, @"%@ o’clock", @"Clock position format, long: {hours} o’clock");
break;
-
+
default:
break;
}
diff --git a/platform/darwin/src/MGLCompassDirectionFormatter.h b/platform/darwin/src/MGLCompassDirectionFormatter.h
index fde26ba42a..b4a3087509 100644
--- a/platform/darwin/src/MGLCompassDirectionFormatter.h
+++ b/platform/darwin/src/MGLCompassDirectionFormatter.h
@@ -1,29 +1,32 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
The `MGLCompassDirectionFormatter` class provides properly formatted
descriptions of absolute headings. For example, a value of `90` may be
formatted as “east”, depending on the locale.
-
+
Use this class to create localized heading strings when displaying directions
irrespective of the user’s current location. To format a direction relative to
the user’s current location, use `MGLClockDirectionFormatter` instead.
*/
+MGL_EXPORT
@interface MGLCompassDirectionFormatter : NSFormatter
/**
The unit style used by this formatter.
-
+
This property defaults to `NSFormattingUnitStyleMedium`.
*/
@property (nonatomic) NSFormattingUnitStyle unitStyle;
/**
Returns a heading string for the provided value.
-
+
@param direction The heading, measured in degrees, where 0° means “due north”
and 90° means “due east”.
@return The heading string appropriately formatted for the formatter’s locale.
diff --git a/platform/darwin/src/MGLCompassDirectionFormatter.m b/platform/darwin/src/MGLCompassDirectionFormatter.m
index c46fe9e4d5..5f0cfae6f7 100644
--- a/platform/darwin/src/MGLCompassDirectionFormatter.m
+++ b/platform/darwin/src/MGLCompassDirectionFormatter.m
@@ -28,7 +28,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_NEbE_SHORT", @"Foundation", nil, @"NEbE", @"Northeast by east, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_ENE_SHORT", @"Foundation", nil, @"ENE", @"East-northeast, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_EbN_SHORT", @"Foundation", nil, @"EbN", @"East by north, short"),
-
+
NSLocalizedStringWithDefaultValue(@"COMPASS_E_SHORT", @"Foundation", nil, @"E", @"East, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_EbS_SHORT", @"Foundation", nil, @"EbS", @"East by south, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_ESE_SHORT", @"Foundation", nil, @"ESE", @"East-southeast, short"),
@@ -37,7 +37,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_SEbS_SHORT", @"Foundation", nil, @"SEbS", @"Southeast by south, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SSE_SHORT", @"Foundation", nil, @"SSE", @"South-southeast, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SbE_SHORT", @"Foundation", nil, @"SbE", @"South by east, short"),
-
+
NSLocalizedStringWithDefaultValue(@"COMPASS_S_SHORT", @"Foundation", nil, @"S", @"South, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SbW_SHORT", @"Foundation", nil, @"SbW", @"South by west, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SSW_SHORT", @"Foundation", nil, @"SSW", @"South-southwest, short"),
@@ -46,7 +46,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_SWbW_SHORT", @"Foundation", nil, @"SWbW", @"Southwest by west, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WSW_SHORT", @"Foundation", nil, @"WSW", @"West-southwest, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WbS_SHORT", @"Foundation", nil, @"WbS", @"West by south, short"),
-
+
NSLocalizedStringWithDefaultValue(@"COMPASS_W_SHORT", @"Foundation", nil, @"W", @"West, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WbN_SHORT", @"Foundation", nil, @"WbN", @"West by north, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WNW_SHORT", @"Foundation", nil, @"WNW", @"West-northwest, short"),
@@ -56,7 +56,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_NNW_SHORT", @"Foundation", nil, @"NNW", @"North-northwest, short"),
NSLocalizedStringWithDefaultValue(@"COMPASS_NbW_SHORT", @"Foundation", nil, @"NbW", @"North by west, short"),
];
-
+
longStrings = @[
NSLocalizedStringWithDefaultValue(@"COMPASS_N_LONG", @"Foundation", nil, @"north", @"North, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_NbE_LONG", @"Foundation", nil, @"north by east", @"North by east, long"),
@@ -66,7 +66,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_NEbE_LONG", @"Foundation", nil, @"northeast by east", @"Northeast by east, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_ENE_LONG", @"Foundation", nil, @"east-northeast", @"East-northeast, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_EbN_LONG", @"Foundation", nil, @"east by north", @"East by north, long"),
-
+
NSLocalizedStringWithDefaultValue(@"COMPASS_E_LONG", @"Foundation", nil, @"east", @"East, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_EbS_LONG", @"Foundation", nil, @"east by south", @"East by south, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_ESE_LONG", @"Foundation", nil, @"east-southeast", @"East-southeast, long"),
@@ -75,7 +75,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_SEbS_LONG", @"Foundation", nil, @"southeast by south", @"Southeast by south, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SSE_LONG", @"Foundation", nil, @"south-southeast", @"South-southeast, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SbE_LONG", @"Foundation", nil, @"south by east", @"South by east, long"),
-
+
NSLocalizedStringWithDefaultValue(@"COMPASS_S_LONG", @"Foundation", nil, @"south", @"South, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SbW_LONG", @"Foundation", nil, @"south by west", @"South by west, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_SSW_LONG", @"Foundation", nil, @"south-southwest", @"South-southwest, long"),
@@ -84,7 +84,7 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_SWbW_LONG", @"Foundation", nil, @"southwest by west", @"Southwest by west, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WSW_LONG", @"Foundation", nil, @"west-southwest", @"West-southwest, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WbS_LONG", @"Foundation", nil, @"west by south", @"West by south, long"),
-
+
NSLocalizedStringWithDefaultValue(@"COMPASS_W_LONG", @"Foundation", nil, @"west", @"West, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WbN_LONG", @"Foundation", nil, @"west by north", @"West by north, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_WNW_LONG", @"Foundation", nil, @"west-northwest", @"West-northwest, long"),
@@ -94,15 +94,15 @@
NSLocalizedStringWithDefaultValue(@"COMPASS_NNW_LONG", @"Foundation", nil, @"north-northwest", @"North-northwest, long"),
NSLocalizedStringWithDefaultValue(@"COMPASS_NbW_LONG", @"Foundation", nil, @"north by west", @"North by west, long"),
];
-
+
NSAssert(shortStrings.count == longStrings.count, @"Long and short compass direction string arrays must have the same size.");
});
-
+
NSInteger cardinalPoint = wrap(round(wrap(direction, 0, 360) / 360 * shortStrings.count), 0, shortStrings.count);
switch (self.unitStyle) {
case NSFormattingUnitStyleShort:
return shortStrings[cardinalPoint];
-
+
case NSFormattingUnitStyleMedium:
case NSFormattingUnitStyleLong:
return longStrings[cardinalPoint];
diff --git a/platform/darwin/src/MGLConversion.h b/platform/darwin/src/MGLConversion.h
new file mode 100644
index 0000000000..d51ebd775c
--- /dev/null
+++ b/platform/darwin/src/MGLConversion.h
@@ -0,0 +1,135 @@
+#import <Foundation/Foundation.h>
+
+#include <mbgl/util/logging.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/optional.hpp>
+
+NS_ASSUME_NONNULL_BEGIN
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+/**
+ A minimal wrapper class conforming to the requirements for `objectMember(v, name)` (see mbgl/style/conversion.hpp)
+ This is necessary because using `NSObject*` as the value type in `optional<NSObject*>` causes problems for the ARC,
+ due to things like `optional(const value_type& __v)`
+ */
+class OptionalNSObjectValue {
+public:
+ OptionalNSObjectValue(NSObject * _Nullable _value) : value(_value) {}
+
+ explicit operator bool() const {
+ return value;
+ }
+
+ NSObject * _Nullable operator*() {
+ NSCAssert(this, @"Expected non-null value.");
+ return value;
+ }
+private:
+ NSObject * _Nullable value;
+};
+
+inline bool isUndefined(const id value) {
+ return !value || value == [NSNull null];
+}
+
+inline bool isArray(const id value) {
+ return [value isKindOfClass:[NSArray class]];
+}
+
+inline bool isObject(const id value) {
+ return [value isKindOfClass:[NSDictionary class]];
+}
+
+inline std::size_t arrayLength(const id value) {
+ NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for getLength().");
+ NSArray *array = value;
+ auto length = [array count];
+ NSCAssert(length <= std::numeric_limits<size_t>::max(), @"Array length out of bounds.");
+ return length;
+}
+
+inline NSObject *arrayMember(const id value, std::size_t i) {
+ NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for get(int).");
+ NSCAssert(i < NSUIntegerMax, @"Index must be less than NSUIntegerMax");
+ return [value objectAtIndex: i];
+}
+
+inline OptionalNSObjectValue objectMember(const id value, const char *key) {
+ NSCAssert([value isKindOfClass:[NSDictionary class]], @"Value must be an NSDictionary for get(string).");
+ NSObject *member = [value objectForKey: @(key)];
+ if (member && member != [NSNull null]) {
+ return { member };
+ } else {
+ return { nullptr };
+ }
+}
+
+// Not implemented (unneeded for MGLStyleFunction conversion):
+// optional<Error> eachMember(const NSObject*, Fn&&)
+
+inline bool _isBool(const id value) {
+ if (![value isKindOfClass:[NSNumber class]]) return false;
+ // char: 32-bit boolean
+ // BOOL: 64-bit boolean
+ NSNumber *number = value;
+ return ((strcmp([number objCType], @encode(char)) == 0) ||
+ (strcmp([number objCType], @encode(BOOL)) == 0));
+}
+
+inline bool _isNumber(const id value) {
+ return [value isKindOfClass:[NSNumber class]] && !_isBool(value);
+}
+
+inline bool _isString(const id value) {
+ return [value isKindOfClass:[NSString class]];
+}
+
+inline optional<bool> toBool(const id value) {
+ if (_isBool(value)) {
+ return ((NSNumber *)value).boolValue;
+ } else {
+ return {};
+ }
+}
+
+inline optional<float> toNumber(const id value) {
+ if (_isNumber(value)) {
+ return ((NSNumber *)value).floatValue;
+ } else {
+ return {};
+ }
+}
+
+inline optional<std::string> toString(const id value) {
+ if (_isString(value)) {
+ return std::string(static_cast<const char *>([value UTF8String]));
+ } else {
+ return {};
+ }
+}
+
+inline optional<mbgl::Value> toValue(const id value) {
+ if (isUndefined(value)) {
+ return {};
+ } else if (_isBool(value)) {
+ return { *toBool(value) };
+ } else if ( _isString(value)) {
+ return { *toString(value) };
+ } else if (_isNumber(value)) {
+ // Need to cast to a double here as the float is otherwise considered a bool...
+ return { static_cast<double>(*toNumber(value)) };
+ } else {
+ return {};
+ }
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
+
+NS_ASSUME_NONNULL_END
+
diff --git a/platform/darwin/src/MGLCoordinateFormatter.h b/platform/darwin/src/MGLCoordinateFormatter.h
index 909c1e8935..63f0de8f19 100644
--- a/platform/darwin/src/MGLCoordinateFormatter.h
+++ b/platform/darwin/src/MGLCoordinateFormatter.h
@@ -1,6 +1,8 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -8,11 +10,12 @@ NS_ASSUME_NONNULL_BEGIN
geographic coordinate pairs. Use this class to create localized coordinate
strings when displaying location information to users.
*/
+MGL_EXPORT
@interface MGLCoordinateFormatter : NSFormatter
/**
Determines whether the output may contain minutes of arc when nonzero.
-
+
The default value of this property is `YES`, causing the receiver to include
minutes of arc in its output. If `allowsSeconds` is `YES`, this property is
ignored and the output always includes minutes of arc.
@@ -21,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Determines whether the output may contain seconds of arc when nonzero.
-
+
The default value of this property is `YES`, causing the receiver to include
seconds of arc in its output.
*/
@@ -29,14 +32,14 @@ NS_ASSUME_NONNULL_BEGIN
/**
The unit style used by this formatter.
-
+
The default value of this property is `NSFormattingUnitStyleMedium`.
*/
@property (nonatomic) NSFormattingUnitStyle unitStyle;
/**
Returns a coordinate string for the provided value.
-
+
@param coordinate The coordinate’s value.
@return The coordinate string appropriately formatted for the formatter’s
locale.
diff --git a/platform/darwin/src/MGLCoordinateFormatter.m b/platform/darwin/src/MGLCoordinateFormatter.m
index 682f771faa..fb577d3be3 100644
--- a/platform/darwin/src/MGLCoordinateFormatter.m
+++ b/platform/darwin/src/MGLCoordinateFormatter.m
@@ -28,7 +28,7 @@
negativeLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_W_SHORT", @"Foundation", nil, @"%@W", @"West longitude format, short: {longitude}");
stringFormat = NSLocalizedStringWithDefaultValue(@"COORD_FMT_SHORT", @"Foundation", nil, @"%@, %@", @"Coordinate pair format, short: {latitude}, {longitude}");
break;
-
+
case NSFormattingUnitStyleMedium:
positiveLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_N_MEDIUM", @"Foundation", nil, @"%@ north", @"North latitude format, medium: {latitude}");
negativeLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_S_MEDIUM", @"Foundation", nil, @"%@ south", @"South latitude format, medium: {latitude}");
@@ -36,7 +36,7 @@
negativeLongitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_W_MEDIUM", @"Foundation", nil, @"%@ west", @"West longitude format, medium: {longitude}");
stringFormat = NSLocalizedStringWithDefaultValue(@"COORD_FMT_MEDIUM", @"Foundation", nil, @"%@, %@", @"Coordinate pair format, medium: {latitude}, {longitude}");
break;
-
+
case NSFormattingUnitStyleLong:
positiveLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_N_LONG", @"Foundation", nil, @"%@ north", @"North latitude format, long: {latitude}");
negativeLatitudeFormat = NSLocalizedStringWithDefaultValue(@"COORD_S_LONG", @"Foundation", nil, @"%@ south", @"South latitude format, long: {latitude}");
@@ -57,7 +57,7 @@
- (NSString *)stringFromLocationDegrees:(CLLocationDegrees)degrees positiveFormat:(NSString *)positiveFormat negativeFormat:(NSString *)negativeFormat {
CLLocationDegrees minutes = (fabs(degrees) - floor(fabs(degrees))) * 60;
CLLocationDegrees seconds = (minutes - floor(minutes)) * 60;
-
+
NSString *degreesFormat;
NSString *minutesFormat;
NSString *secondsFormat;
@@ -71,7 +71,7 @@
degreesMinutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DM_SHORT", @"Foundation", nil, @"%@%@", @"Coordinate format, short: {degrees}{minutes}");
degreesMinutesSecondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_DMS_SHORT", @"Foundation", nil, @"%@%@%@", @"Coordinate format, short: {degrees}{minutes}{seconds}");
break;
-
+
case NSFormattingUnitStyleMedium:
degreesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DEG_MEDIUM", @"Foundation", nil, @"%d°", @"Degrees format, medium: {degrees}");
minutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_MIN_MEDIUM", @"Foundation", nil, @"%d′", @"Minutes format, medium: {minutes}");
@@ -79,7 +79,7 @@
degreesMinutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DM_MEDIUM", @"Foundation", nil, @"%@%@", @"Coordinate format, medium: {degrees}{minutes}");
degreesMinutesSecondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_DMS_MEDIUM", @"Foundation", nil, @"%@%@%@", @"Coordinate format, medium: {degrees}{minutes}{seconds}");
break;
-
+
case NSFormattingUnitStyleLong:
degreesFormat = NSLocalizedStringWithDefaultValue(@"COORD_DEG_LONG", @"Foundation", nil, @"%d degree(s)", @"Degrees format, long");
minutesFormat = NSLocalizedStringWithDefaultValue(@"COORD_MIN_LONG", @"Foundation", nil, @"%d minute(s)", @"Minutes format, long");
@@ -88,9 +88,9 @@
degreesMinutesSecondsFormat = NSLocalizedStringWithDefaultValue(@"COORD_DMS_LONG", @"Foundation", nil, @"%@, %@, and %@", @"Coordinate format, long: {degrees}{minutes}{seconds}");
break;
}
-
+
NSString *degreesString = [NSString stringWithFormat:degreesFormat, (int)floor(fabs(degrees))];
-
+
NSString *string;
if (trunc(seconds) > 0 && self.allowsSeconds) {
NSString *minutesString = [NSString stringWithFormat:minutesFormat, (int)floor(minutes)];
@@ -104,7 +104,7 @@
} else {
string = [NSString stringWithFormat:degreesFormat, (int)round(fabs(degrees))];
}
-
+
if (degrees == 0) {
return string;
}
diff --git a/platform/darwin/src/MGLDistanceFormatter.h b/platform/darwin/src/MGLDistanceFormatter.h
new file mode 100644
index 0000000000..46aad9a940
--- /dev/null
+++ b/platform/darwin/src/MGLDistanceFormatter.h
@@ -0,0 +1,26 @@
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+
+#import "MGLFoundation.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ `MGLDistanceFormatter` implements a formatter object meant to be used for
+ geographic distances. The user’s current locale will be used by default
+ but it can be overriden by changing the locale property of the numberFormatter.
+ */
+MGL_EXPORT
+@interface MGLDistanceFormatter : NSLengthFormatter
+
+/**
+ Returns a localized formatted string for the provided distance.
+
+ @param distance The distance, measured in meters.
+ @return A localized formatted distance string including units.
+ */
+- (NSString *)stringFromDistance:(CLLocationDistance)distance;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLDistanceFormatter.m b/platform/darwin/src/MGLDistanceFormatter.m
new file mode 100644
index 0000000000..e77e48b512
--- /dev/null
+++ b/platform/darwin/src/MGLDistanceFormatter.m
@@ -0,0 +1,35 @@
+#import "MGLDistanceFormatter.h"
+
+@interface MGLDistanceFormatter()
+@end
+
+@implementation MGLDistanceFormatter
+
+static const CLLocationDistance METERS_PER_MILE = 1609.344;
+static const double YARDS_PER_MILE = 1760.0;
+static const double FEET_PER_MILE = YARDS_PER_MILE * 3.0;
+
+- (NSString *)stringFromDistance:(CLLocationDistance)distance {
+ double miles = distance / METERS_PER_MILE;
+ double feet = miles * FEET_PER_MILE;
+
+ NSLengthFormatterUnit unit = NSLengthFormatterUnitMillimeter;
+ [self unitStringFromMeters:distance usedUnit:&unit];
+
+ self.numberFormatter.roundingIncrement = @0.25;
+
+ if (unit == NSLengthFormatterUnitYard) {
+ if (miles > 0.2) {
+ unit = NSLengthFormatterUnitMile;
+ return [self stringFromValue:miles unit:unit];
+ } else {
+ unit = NSLengthFormatterUnitFoot;
+ self.numberFormatter.roundingIncrement = @50;
+ return [self stringFromValue:feet unit:unit];
+ }
+ } else {
+ return [self stringFromMeters:distance];
+ }
+}
+
+@end
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index 30abcb1934..2380a817e3 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLPolyline.h"
#import "MGLPolygon.h"
#import "MGLPointAnnotation.h"
@@ -13,14 +14,14 @@ NS_ASSUME_NONNULL_BEGIN
contained in an `MGLShapeSource` or `MGLVectorSource` object. Each concrete
subclass of `MGLShape` in turn has a subclass that conforms to this protocol. A
feature object associates a shape with an optional identifier and attributes.
-
+
You can add custom data to display on the map by creating feature objects and
adding them to an `MGLShapeSource` using the
`-[MGLShapeSource initWithIdentifier:shape:options:]` method or
`MGLShapeSource.shape` property. Similarly, you can add `MGLPointFeature`,
`MGLPolylineFeature`, and `MGLPolygonFeature` objects to the map as annotations
using `-[MGLMapView addAnnotations:]` and related methods.
-
+
In addition to adding data to the map, you can also extract data from the map:
`-[MGLMapView visibleFeaturesAtPoint:]` and related methods return feature
objects that correspond to features in the source. This enables you to inspect
@@ -32,12 +33,12 @@ NS_ASSUME_NONNULL_BEGIN
/**
An object that uniquely identifies the feature in its containing content
source.
-
+
You can configure an `MGLVectorStyleLayer` object to include or exclude a
specific feature in an `MGLShapeSource` or `MGLVectorSource`. In the
`MGLVectorStyleLayer.predicate` property, compare the special `$id` attribute
to the feature’s identifier.
-
+
In vector tiles loaded by `MGLVectorSource` objects, the identifier corresponds
to the
<a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#42-features">feature identifier</a>
@@ -45,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
this property is `nil`. If specified, the identifier may be an integer,
floating-point number, or string. These data types are mapped to instances of
the following Foundation classes:
-
+
<table>
<thead>
<tr><th>In the tile source</th><th>This property</th></tr>
@@ -56,12 +57,12 @@ NS_ASSUME_NONNULL_BEGIN
<tr><td>String</td> <td><code>NSString</code></td></tr>
</tbody>
</table>
-
+
For details about the identifiers used in most Mapbox-provided styles, consult
the
<a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a>
layer reference.
-
+
The identifier should be set before adding the feature to an `MGLShapeSource`
object; setting it afterwards has no effect on the map’s contents. While it is
possible to change this value on feature instances obtained from
@@ -72,7 +73,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
A dictionary of attributes for this feature.
-
+
You can configure an `MGLVectorStyleLayer` object to include or exclude a
specific feature in an `MGLShapeSource` or `MGLVectorSource`. In the
`MGLVectorStyleLayer.predicate` property, compare a key of the attribute
@@ -81,20 +82,29 @@ NS_ASSUME_NONNULL_BEGIN
a value above 50 to the important features’ `importance` attribute, then set
`MGLVectorStyleLayer.predicate` to an `NSPredicate` with the format
`importance > 50`.
-
- You can also configure some attributes of an `MGLSymbolStyleLayer` object to
- include the value of an attribute in this dictionary whenever it renders this
- feature. For example, to label features in an `MGLShapeSource` object by their
- names, you can assign a `name` attribute to each of the source’s features, then
- set `MGLSymbolStyleLayer.textField` to an `MGLStyleValue` object containing the
- string `{name}`.
-
+
+ You can also configure many layout and paint attributes of an `MGLStyleLayer`
+ object to match the value of an attribute in this dictionary whenever it
+ renders this feature. For example, if you display features in an
+ `MGLShapeSource` using an `MGLCircleStyleLayer`, you can assign a `halfway`
+ attribute to each of the source’s features, then set
+ `MGLCircleStyleLayer.circleRadius` to an `MGLStyleValue` object with an
+ interpolation mode of `MGLInterpolationModeIdentity` and an attribute name of
+ `halfway`.
+
+ The `MGLSymbolStyleLayer.textField` and `MGLSymbolStyleLayer.iconImageName`
+ properties allow you to use attributes yet another way. For example, to label
+ features in an `MGLShapeSource` object by their names, you can assign a `name`
+ attribute to each of the source’s features, then set
+ `MGLSymbolStyleLayer.textField` to an `MGLStyleValue` object containing the
+ raw string value `{name}`.
+
In vector tiles loaded by `MGLVectorSource` objects, the keys and values of
each feature’s attribute dictionary are determined by the source. Each
attribute name is a string, while each attribute value may be a null value,
Boolean value, integer, floating-point number, or string. These data types are
mapped to instances of the following Foundation classes:
-
+
<table>
<thead>
<tr><th>In the tile source</th><th>In this dictionary</th></tr>
@@ -107,7 +117,7 @@ NS_ASSUME_NONNULL_BEGIN
<tr><td>String</td> <td><code>NSString</code></td></tr>
</tbody>
</table>
-
+
For details about the attribute names and values found in Mapbox-provided
vector tile sources, consult the
<a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a>
@@ -115,6 +125,15 @@ NS_ASSUME_NONNULL_BEGIN
<a href="https://www.mapbox.com/vector-tiles/mapbox-terrain/">Mapbox Terrain</a>
layer references.
+ When adding a feature to an `MGLShapeSource`, use the same Foundation types
+ listed above for each attribute value. In addition to the Foundation types, you
+ may also set an attribute to an `NSColor` (macOS) or `UIColor` (iOS), which
+ will be converted into its
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#types-color">CSS string representation</a>
+ when the feature is added to an `MGLShapeSource`. This can be convenient when
+ using the attribute to supply a value for a color-typed layout or paint
+ attribute via the `MGLInterpolationModeIdentity` interpolation mode.
+
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
@@ -125,7 +144,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns the feature attribute for the given attribute name.
-
+
See the `attributes` property’s documentation for details on keys and values
associated with this method.
*/
@@ -134,10 +153,10 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a dictionary that can be serialized as a GeoJSON Feature representation
of an instance of an `MGLFeature` subclass.
-
- The dictionary includes a `geometry` key corresponding to the receiver’s
- underlying geometry data, a `properties` key corresponding to the receiver’s
- `attributes` property, and an `id` key corresponding to the receiver’s
+
+ The dictionary includes a `geometry` key corresponding to the receiver’s
+ underlying geometry data, a `properties` key corresponding to the receiver’s
+ `attributes` property, and an `id` key corresponding to the receiver’s
`identifier` property.
*/
- (NS_DICTIONARY_OF(NSString *, id) *)geoJSONDictionary;
@@ -148,17 +167,19 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLPointFeature` object associates a point shape with an optional
identifier and attributes.
*/
+MGL_EXPORT
@interface MGLPointFeature : MGLPointAnnotation <MGLFeature>
@end
/**
An `MGLPolylineFeature` object associates a polyline shape with an optional
identifier and attributes.
-
+
A polyline feature is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.4">LineString</a>
feature in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPolylineFeature : MGLPolyline <MGLFeature>
@end
@@ -166,17 +187,19 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLPolygonFeature` object associates a polygon shape with an optional
identifier and attributes.
*/
+MGL_EXPORT
@interface MGLPolygonFeature : MGLPolygon <MGLFeature>
@end
/**
An `MGLPointCollectionFeature` object associates a point collection with an
optional identifier and attributes.
-
+
A point collection feature is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.3">MultiPoint</a>
feature in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPointCollectionFeature : MGLPointCollection <MGLFeature>
@end
@@ -186,11 +209,12 @@ NS_ASSUME_NONNULL_BEGIN
/**
An `MGLMultiPolylineFeature` object associates a multipolyline shape with an
optional identifier and attributes.
-
+
A multipolyline feature is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.5">MultiLineString</a>
feature in GeoJSON.
*/
+MGL_EXPORT
@interface MGLMultiPolylineFeature : MGLMultiPolyline <MGLFeature>
@end
@@ -198,17 +222,19 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLMultiPolygonFeature` object associates a multipolygon shape with an
optional identifier and attributes.
*/
+MGL_EXPORT
@interface MGLMultiPolygonFeature : MGLMultiPolygon <MGLFeature>
@end
/**
An `MGLShapeCollectionFeature` object associates a shape collection with an
optional identifier and attributes.
-
+
A shape collection feature is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.3">feature collection</a>
in GeoJSON.
*/
+MGL_EXPORT
@interface MGLShapeCollectionFeature : MGLShapeCollection <MGLFeature>
@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLShape<MGLFeature> *) *shapes;
diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm
index 3bd7eae535..e169ee19bb 100644
--- a/platform/darwin/src/MGLFeature.mm
+++ b/platform/darwin/src/MGLFeature.mm
@@ -225,21 +225,21 @@ public:
feature.coordinate = toLocationCoordinate2D(geometry);
return feature;
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::LineString<T> &geometry) const {
std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(geometry);
return [MGLPolylineFeature polylineWithCoordinates:&coordinates[0] count:coordinates.size()];
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::Polygon<T> &geometry) const {
return toShape<MGLPolygonFeature>(geometry);
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::MultiPoint<T> &geometry) const {
std::vector<CLLocationCoordinate2D> coordinates = toLocationCoordinates2D(geometry);
return [[MGLPointCollectionFeature alloc] initWithCoordinates:&coordinates[0] count:coordinates.size()];
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::MultiLineString<T> &geometry) const {
NSMutableArray *polylines = [NSMutableArray arrayWithCapacity:geometry.size()];
for (auto &lineString : geometry) {
@@ -247,19 +247,19 @@ public:
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:&coordinates[0] count:coordinates.size()];
[polylines addObject:polyline];
}
-
+
return [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::MultiPolygon<T> &geometry) const {
NSMutableArray *polygons = [NSMutableArray arrayWithCapacity:geometry.size()];
for (auto &polygon : geometry) {
[polygons addObject:toShape(polygon)];
}
-
+
return [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
}
-
+
MGLShape <MGLFeature> * operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()];
for (auto &geometry : collection) {
@@ -269,19 +269,19 @@ public:
}
return [MGLShapeCollectionFeature shapeCollectionWithShapes:shapes];
}
-
+
private:
static CLLocationCoordinate2D toLocationCoordinate2D(const mbgl::Point<T> &point) {
return CLLocationCoordinate2DMake(point.y, point.x);
}
-
+
static std::vector<CLLocationCoordinate2D> toLocationCoordinates2D(const std::vector<mbgl::Point<T>> &points) {
std::vector<CLLocationCoordinate2D> coordinates;
coordinates.reserve(points.size());
std::transform(points.begin(), points.end(), std::back_inserter(coordinates), toLocationCoordinate2D);
return coordinates;
}
-
+
template<typename U = MGLPolygon>
static U *toShape(const mbgl::Polygon<T> &geometry) {
auto &linearRing = geometry.front();
@@ -296,7 +296,7 @@ private:
[innerPolygons addObject:innerPolygon];
}
}
-
+
return [U polygonWithCoordinates:&coordinates[0] count:coordinates.size() interiorPolygons:innerPolygons];
}
};
@@ -309,12 +309,12 @@ public:
MGLShape <MGLFeature> *shape = mapbox::geometry::geometry<T>::visit(geometry, evaluator);
return shape;
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::Feature &feature) const {
MGLShape <MGLFeature> *shape = (MGLShape <MGLFeature> *)MGLFeatureFromMBGLFeature(feature);
return shape;
}
-
+
MGLShape <MGLFeature> * operator()(const mbgl::FeatureCollection &collection) const {
NSMutableArray *shapes = [NSMutableArray arrayWithCapacity:collection.size()];
for (const auto &feature : collection) {
@@ -345,7 +345,7 @@ id <MGLFeature> MGLFeatureFromMBGLFeature(const mbgl::Feature &feature) {
shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, ValueEvaluator());
}
shape.attributes = attributes;
-
+
return shape;
}
diff --git a/platform/darwin/src/MGLFeature_Private.h b/platform/darwin/src/MGLFeature_Private.h
index 3277a94d5b..4137200b98 100644
--- a/platform/darwin/src/MGLFeature_Private.h
+++ b/platform/darwin/src/MGLFeature_Private.h
@@ -1,3 +1,4 @@
+#import "MGLFoundation.h"
#import "MGLFeature.h"
#import "MGLShape.h"
@@ -11,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
Returns an array of `MGLFeature` objects converted from the given vector of
vector tile features.
*/
+MGL_EXPORT
NS_ARRAY_OF(MGLShape <MGLFeature> *) *MGLFeaturesFromMBGLFeatures(const std::vector<mbgl::Feature> &features);
/**
@@ -26,7 +28,7 @@ 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
+ returns the feature object with converted `mbgl::FeatureIdentifier` and
`mbgl::PropertyMap` properties.
*/
mbgl::Feature mbglFeature(mbgl::Feature feature, id identifier, NSDictionary *attributes);
diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h
index d05b21eb51..a5baf2308c 100644
--- a/platform/darwin/src/MGLFillStyleLayer.h
+++ b/platform/darwin/src/MGLFillStyleLayer.h
@@ -1,6 +1,7 @@
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -8,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Controls the translation reference point.
-
+
Values of this type are used in the `MGLFillStyleLayer.fillTranslationAnchor`
property.
*/
@@ -31,15 +32,15 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
multipolygon features in vector tiles loaded by an `MGLVectorSource` object or
`MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or
`MGLMultiPolygonFeature` instances in an `MGLShapeSource` object.
-
+
You can access an existing fill style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new fill style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
### Example
-
+
```swift
let layer = MGLFillStyleLayer(identifier: "parks", source: parks)
layer.sourceLayerIdentifier = "parks"
@@ -48,6 +49,7 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLFillStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Paint Attributes
@@ -62,6 +64,12 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-antialias"><code>fill-antialias</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable, getter=isFillAntialiased) MGLStyleValue<NSNumber *> *fillAntialiased;
@@ -77,6 +85,22 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
This property is only applied to the style if `fillPattern` is set to `nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *fillColor;
#else
@@ -89,6 +113,22 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
This property is only applied to the style if `fillPattern` is set to `nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *fillColor;
#endif
@@ -100,6 +140,22 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `1`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillOpacity;
@@ -110,6 +166,22 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
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.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *fillOutlineColor;
#else
@@ -119,6 +191,22 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
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.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *fillOutlineColor;
#endif
@@ -126,6 +214,12 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
/**
Name of image in sprite to use for drawing image fills. For seamless patterns,
image width and height must be a factor of two (2, 4, 8, ..., 512).
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *fillPattern;
@@ -142,6 +236,13 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-translate"><code>fill-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillTranslation;
#else
@@ -157,6 +258,13 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-translate"><code>fill-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillTranslation;
#endif
@@ -176,6 +284,12 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-translate-anchor"><code>fill-translate-anchor</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillTranslationAnchor;
diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm
index ec736d8825..6212bce410 100644
--- a/platform/darwin/src/MGLFillStyleLayer.mm
+++ b/platform/darwin/src/MGLFillStyleLayer.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLFillStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLFillTranslationAnchor, {
@@ -52,7 +54,7 @@ namespace mbgl {
- (NSString *)sourceIdentifier
{
MGLAssertStyleLayerIsValid();
-
+
return @(self.rawLayer->getSourceID().c_str());
}
@@ -136,7 +138,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)isFillAntialiased {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillAntialias() ?: self.rawLayer->getDefaultFillAntialias();
+ auto propertyValue = self.rawLayer->getFillAntialias();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultFillAntialias());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -150,43 +155,52 @@ namespace mbgl {
- (void)setFillColor:(MGLStyleValue<MGLColor *> *)fillColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(fillColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(fillColor);
self.rawLayer->setFillColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)fillColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillColor() ?: self.rawLayer->getDefaultFillColor();
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getFillColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillColor());
+ }
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setFillOpacity:(MGLStyleValue<NSNumber *> *)fillOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(fillOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(fillOpacity);
self.rawLayer->setFillOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)fillOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillOpacity() ?: self.rawLayer->getDefaultFillOpacity();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getFillOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillOpacity());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setFillOutlineColor:(MGLStyleValue<MGLColor *> *)fillOutlineColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(fillOutlineColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(fillOutlineColor);
self.rawLayer->setFillOutlineColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)fillOutlineColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillOutlineColor() ?: self.rawLayer->getDefaultFillOutlineColor();
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getFillOutlineColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillOutlineColor());
+ }
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setFillPattern:(MGLStyleValue<NSString *> *)fillPattern {
@@ -199,21 +213,27 @@ namespace mbgl {
- (MGLStyleValue<NSString *> *)fillPattern {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillPattern() ?: self.rawLayer->getDefaultFillPattern();
+ auto propertyValue = self.rawLayer->getFillPattern();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultFillPattern());
+ }
return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
- (void)setFillTranslation:(MGLStyleValue<NSValue *> *)fillTranslation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(fillTranslation);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(fillTranslation);
self.rawLayer->setFillTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)fillTranslation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillTranslate() ?: self.rawLayer->getDefaultFillTranslate();
+ auto propertyValue = self.rawLayer->getFillTranslate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultFillTranslate());
+ }
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
@@ -234,7 +254,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)fillTranslationAnchor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getFillTranslateAnchor() ?: self.rawLayer->getDefaultFillTranslateAnchor();
+ auto propertyValue = self.rawLayer->getFillTranslateAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultFillTranslateAnchor());
+ }
return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillTranslationAnchor>().toEnumStyleValue(propertyValue);
}
diff --git a/platform/darwin/src/MGLForegroundStyleLayer.h b/platform/darwin/src/MGLForegroundStyleLayer.h
index 642dde4992..87763f4634 100644
--- a/platform/darwin/src/MGLForegroundStyleLayer.h
+++ b/platform/darwin/src/MGLForegroundStyleLayer.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLStyleLayer.h"
NS_ASSUME_NONNULL_BEGIN
@@ -9,11 +10,12 @@ NS_ASSUME_NONNULL_BEGIN
/**
`MGLForegroundStyleLayer` is an abstract superclass for style layers whose
content is defined by an `MGLSource` object.
-
+
Do not create instances of this class directly, and do not create your own
subclasses of this class. Instead, create instances of `MGLRasterStyleLayer`
and the concrete subclasses of `MGLVectorStyleLayer`.
*/
+MGL_EXPORT
@interface MGLForegroundStyleLayer : MGLStyleLayer
#pragma mark Initializing a Style Layer
@@ -23,11 +25,11 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a foreground style layer initialized with an identifier and source.
-
+
After initializing and configuring the style layer, add it to a map view’s
style using the `-[MGLStyle addLayer:]` or
`-[MGLStyle insertLayer:belowLayer:]` method.
-
+
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param source The source from which to obtain the data to style. If the source
diff --git a/platform/darwin/src/MGLFoundation.h b/platform/darwin/src/MGLFoundation.h
new file mode 100644
index 0000000000..3400c63979
--- /dev/null
+++ b/platform/darwin/src/MGLFoundation.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#import <Foundation/Foundation.h>
+
+#define MGL_EXPORT __attribute__((visibility ("default")))
diff --git a/platform/darwin/src/MGLFoundation.mm b/platform/darwin/src/MGLFoundation.mm
new file mode 100644
index 0000000000..1cc56de298
--- /dev/null
+++ b/platform/darwin/src/MGLFoundation.mm
@@ -0,0 +1,4 @@
+#import "MGLFoundation_Private.h"
+
+/// Initializes the run loop shim that lives on the main thread.
+mbgl::util::RunLoop mgl_runLoop;
diff --git a/platform/darwin/src/MGLFoundation_Private.h b/platform/darwin/src/MGLFoundation_Private.h
new file mode 100644
index 0000000000..940bb1df69
--- /dev/null
+++ b/platform/darwin/src/MGLFoundation_Private.h
@@ -0,0 +1,5 @@
+#import "MGLFoundation.h"
+
+#include <mbgl/util/run_loop.hpp>
+
+extern mbgl::util::RunLoop mgl_runLoop;
diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h
index 8e36b86d96..9fcb9dd37c 100644
--- a/platform/darwin/src/MGLGeometry.h
+++ b/platform/darwin/src/MGLGeometry.h
@@ -2,6 +2,8 @@
#import <CoreLocation/CoreLocation.h>
#import <CoreGraphics/CGBase.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/** Defines the area spanned by an `MGLCoordinateBounds`. */
@@ -33,7 +35,7 @@ NS_INLINE BOOL MGLCoordinateSpanEqualToCoordinateSpan(MGLCoordinateSpan span1, M
}
/** An area of zero width and zero height. */
-extern const MGLCoordinateSpan MGLCoordinateSpanZero;
+extern MGL_EXPORT const MGLCoordinateSpan MGLCoordinateSpanZero;
/** A rectangular area as measured on a two-dimensional map projection. */
typedef struct MGLCoordinateBounds {
@@ -99,7 +101,7 @@ NS_INLINE MGLCoordinateBounds MGLCoordinateBoundsOffset(MGLCoordinateBounds boun
/**
Returns `YES` if the coordinate bounds covers no area.
-
+
@note A bounds may be empty but have a non-zero coordinate span (e.g., when its
northeast point lies due north of its southwest point).
*/
diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm
index 70f00afd2f..8c0c5f9cb7 100644
--- a/platform/darwin/src/MGLGeometry.mm
+++ b/platform/darwin/src/MGLGeometry.mm
@@ -1,12 +1,14 @@
#import "MGLGeometry_Private.h"
+#import "MGLFoundation.h"
+
#import <mbgl/util/projection.hpp>
/** Vertical field of view, measured in degrees, for determining the altitude
of the viewpoint.
-
- TransformState::getProjMatrix() assumes a vertical field of view of
- 2 arctan ⅓ rad ≈ 36.9°, but MapKit uses a vertical field of view of 30°.
+
+ TransformState::getProjMatrix() has a variable vertical field of view that
+ defaults to 2 arctan ⅓ rad ≈ 36.9° but MapKit uses a vertical field of view of 30°.
flyTo() assumes a field of view of 2 arctan ½ rad. */
const CLLocationDegrees MGLAngularFieldOfView = 30;
@@ -30,6 +32,7 @@ CGRect MGLExtendRect(CGRect rect, CGPoint point) {
return rect;
}
+MGL_EXPORT
CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLocationDegrees latitude, CGSize size) {
CLLocationDistance metersPerPixel = mbgl::Projection::getMetersPerPixelAtLatitude(latitude, zoomLevel);
CLLocationDistance metersTall = metersPerPixel * size.height;
@@ -37,6 +40,7 @@ CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLo
return altitude * std::sin(M_PI_2 - MGLRadiansFromDegrees(pitch)) / std::sin(M_PI_2);
}
+MGL_EXPORT
double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size) {
CLLocationDistance eyeAltitude = altitude / std::sin(M_PI_2 - MGLRadiansFromDegrees(pitch)) * std::sin(M_PI_2);
CLLocationDistance metersTall = eyeAltitude * 2 * std::tan(MGLRadiansFromDegrees(MGLAngularFieldOfView) / 2.);
diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h
index fc57460128..e6b37b3530 100644
--- a/platform/darwin/src/MGLGeometry_Private.h
+++ b/platform/darwin/src/MGLGeometry_Private.h
@@ -45,7 +45,7 @@ NS_INLINE mbgl::EdgeInsets MGLEdgeInsetsFromNSEdgeInsets(NSEdgeInsets insets) {
#endif
/** Converts a map zoom level to a camera altitude.
-
+
@param zoomLevel The zoom level to convert.
@param pitch The camera pitch, measured in degrees.
@param latitude The latitude of the point at the center of the viewport.
@@ -54,7 +54,7 @@ NS_INLINE mbgl::EdgeInsets MGLEdgeInsetsFromNSEdgeInsets(NSEdgeInsets insets) {
CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLocationDegrees latitude, CGSize size);
/** Converts a camera altitude to a map zoom level.
-
+
@param altitude The altitude to convert, measured in meters.
@param pitch The camera pitch, measured in degrees.
@param latitude The latitude of the point at the center of the viewport.
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index 9b37a97460..23a1f8f131 100644
--- a/platform/darwin/src/MGLLineStyleLayer.h
+++ b/platform/darwin/src/MGLLineStyleLayer.h
@@ -1,6 +1,7 @@
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -8,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
The display of line endings.
-
+
Values of this type are used in the `MGLLineStyleLayer.lineCap`
property.
*/
@@ -33,7 +34,7 @@ typedef NS_ENUM(NSUInteger, MGLLineCap) {
/**
The display of lines when joining.
-
+
Values of this type are used in the `MGLLineStyleLayer.lineJoin`
property.
*/
@@ -58,7 +59,7 @@ typedef NS_ENUM(NSUInteger, MGLLineJoin) {
/**
Controls the translation reference point.
-
+
Values of this type are used in the `MGLLineStyleLayer.lineTranslationAnchor`
property.
*/
@@ -81,28 +82,29 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
multipolyline features in vector tiles loaded by an `MGLVectorSource` object or
`MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or
`MGLMultiPolylineFeature` instances in an `MGLShapeSource` object.
-
+
You can access an existing line style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new line style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
### Example
-
+
```swift
let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
layer.sourceLayerIdentifier = "trails"
- layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [
- 14: MGLStyleValue(rawValue: 2),
- 18: MGLStyleValue(rawValue: 20),
- ])
+ layer.lineWidth = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: [14: MGLStyleValue(rawValue: 2),
+ 18: MGLStyleValue(rawValue: 20)],
+ options: [.interpolationBase: 1.5])
layer.lineColor = MGLStyleValue(rawValue: .brown)
layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round))
layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking")
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLLineStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Layout Attributes
@@ -113,6 +115,12 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSValue` object containing `MGLLineCapButt`. Set this property to `nil` to
reset it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineCap;
@@ -122,6 +130,12 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSValue` object containing `MGLLineJoinMiter`. Set this property to `nil` to
reset it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineJoin;
@@ -135,6 +149,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This property is only applied to the style if `lineJoin` is set to an
`MGLStyleValue` object containing an `NSValue` object containing
`MGLLineJoinMiter`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineMiterLimit;
@@ -148,6 +169,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This property is only applied to the style if `lineJoin` is set to an
`MGLStyleValue` object containing an `NSValue` object containing
`MGLLineJoinRound`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineRoundLimit;
@@ -161,6 +189,22 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `0`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineBlur;
@@ -174,6 +218,22 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This property is only applied to the style if `linePattern` is set to `nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *lineColor;
#else
@@ -186,6 +246,22 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This property is only applied to the style if `linePattern` is set to `nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *lineColor;
#endif
@@ -203,6 +279,12 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-line-dasharray"><code>line-dasharray</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSArray<NSNumber *> *> *lineDashPattern;
@@ -217,6 +299,22 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `0`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineGapWidth;
@@ -231,6 +329,22 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `0`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineOffset;
@@ -240,12 +354,34 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `1`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineOpacity;
/**
Name of image in style images to use for drawing image lines. For seamless
patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *linePattern;
@@ -262,6 +398,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-line-translate"><code>line-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslation;
#else
@@ -277,6 +420,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-line-translate"><code>line-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslation;
#endif
@@ -296,6 +446,12 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-line-translate-anchor"><code>line-translate-anchor</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslationAnchor;
@@ -309,6 +465,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `1`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineWidth;
diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm
index f6884fad15..6f1d2ee249 100644
--- a/platform/darwin/src/MGLLineStyleLayer.mm
+++ b/platform/darwin/src/MGLLineStyleLayer.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLLineStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/line_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLLineCap, {
@@ -64,7 +66,7 @@ namespace mbgl {
- (NSString *)sourceIdentifier
{
MGLAssertStyleLayerIsValid();
-
+
return @(self.rawLayer->getSourceID().c_str());
}
@@ -148,7 +150,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)lineCap {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineCap() ?: self.rawLayer->getDefaultLineCap();
+ auto propertyValue = self.rawLayer->getLineCap();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::LineCapType, NSValue *, mbgl::style::LineCapType, MGLLineCap>().toEnumStyleValue(self.rawLayer->getDefaultLineCap());
+ }
return MGLStyleValueTransformer<mbgl::style::LineCapType, NSValue *, mbgl::style::LineCapType, MGLLineCap>().toEnumStyleValue(propertyValue);
}
@@ -162,35 +167,44 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)lineJoin {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineJoin() ?: self.rawLayer->getDefaultLineJoin();
+ auto propertyValue = self.rawLayer->getLineJoin();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *, mbgl::style::LineJoinType, MGLLineJoin>().toEnumStyleValue(self.rawLayer->getDefaultLineJoin());
+ }
return MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *, mbgl::style::LineJoinType, MGLLineJoin>().toEnumStyleValue(propertyValue);
}
- (void)setLineMiterLimit:(MGLStyleValue<NSNumber *> *)lineMiterLimit {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineMiterLimit);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(lineMiterLimit);
self.rawLayer->setLineMiterLimit(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineMiterLimit {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineMiterLimit() ?: self.rawLayer->getDefaultLineMiterLimit();
+ auto propertyValue = self.rawLayer->getLineMiterLimit();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultLineMiterLimit());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setLineRoundLimit:(MGLStyleValue<NSNumber *> *)lineRoundLimit {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineRoundLimit);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(lineRoundLimit);
self.rawLayer->setLineRoundLimit(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineRoundLimit {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineRoundLimit() ?: self.rawLayer->getDefaultLineRoundLimit();
+ auto propertyValue = self.rawLayer->getLineRoundLimit();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultLineRoundLimit());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -199,29 +213,35 @@ namespace mbgl {
- (void)setLineBlur:(MGLStyleValue<NSNumber *> *)lineBlur {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineBlur);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(lineBlur);
self.rawLayer->setLineBlur(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineBlur {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineBlur() ?: self.rawLayer->getDefaultLineBlur();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getLineBlur();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultLineBlur());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setLineColor:(MGLStyleValue<MGLColor *> *)lineColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(lineColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(lineColor);
self.rawLayer->setLineColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)lineColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineColor() ?: self.rawLayer->getDefaultLineColor();
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getLineColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultLineColor());
+ }
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setLineDashPattern:(MGLStyleValue<NSArray<NSNumber *> *> *)lineDashPattern {
@@ -234,7 +254,10 @@ namespace mbgl {
- (MGLStyleValue<NSArray<NSNumber *> *> *)lineDashPattern {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineDasharray() ?: self.rawLayer->getDefaultLineDasharray();
+ auto propertyValue = self.rawLayer->getLineDasharray();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::vector<float>, NSArray<NSNumber *> *, float>().toStyleValue(self.rawLayer->getDefaultLineDasharray());
+ }
return MGLStyleValueTransformer<std::vector<float>, NSArray<NSNumber *> *, float>().toStyleValue(propertyValue);
}
@@ -248,43 +271,52 @@ namespace mbgl {
- (void)setLineGapWidth:(MGLStyleValue<NSNumber *> *)lineGapWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineGapWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(lineGapWidth);
self.rawLayer->setLineGapWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineGapWidth {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineGapWidth() ?: self.rawLayer->getDefaultLineGapWidth();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getLineGapWidth();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultLineGapWidth());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setLineOffset:(MGLStyleValue<NSNumber *> *)lineOffset {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineOffset);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(lineOffset);
self.rawLayer->setLineOffset(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineOffset {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineOffset() ?: self.rawLayer->getDefaultLineOffset();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getLineOffset();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultLineOffset());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setLineOpacity:(MGLStyleValue<NSNumber *> *)lineOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(lineOpacity);
self.rawLayer->setLineOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineOpacity() ?: self.rawLayer->getDefaultLineOpacity();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getLineOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultLineOpacity());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setLinePattern:(MGLStyleValue<NSString *> *)linePattern {
@@ -297,21 +329,27 @@ namespace mbgl {
- (MGLStyleValue<NSString *> *)linePattern {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLinePattern() ?: self.rawLayer->getDefaultLinePattern();
+ auto propertyValue = self.rawLayer->getLinePattern();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultLinePattern());
+ }
return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
- (void)setLineTranslation:(MGLStyleValue<NSValue *> *)lineTranslation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(lineTranslation);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(lineTranslation);
self.rawLayer->setLineTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)lineTranslation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineTranslate() ?: self.rawLayer->getDefaultLineTranslate();
+ auto propertyValue = self.rawLayer->getLineTranslate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultLineTranslate());
+ }
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
@@ -332,7 +370,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)lineTranslationAnchor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineTranslateAnchor() ?: self.rawLayer->getDefaultLineTranslateAnchor();
+ auto propertyValue = self.rawLayer->getLineTranslateAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLLineTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultLineTranslateAnchor());
+ }
return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLLineTranslationAnchor>().toEnumStyleValue(propertyValue);
}
@@ -346,14 +387,17 @@ namespace mbgl {
- (void)setLineWidth:(MGLStyleValue<NSNumber *> *)lineWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(lineWidth);
self.rawLayer->setLineWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineWidth {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getLineWidth() ?: self.rawLayer->getDefaultLineWidth();
+ auto propertyValue = self.rawLayer->getLineWidth();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultLineWidth());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
diff --git a/platform/darwin/src/MGLMapCamera.h b/platform/darwin/src/MGLMapCamera.h
index 7d26372400..7ce5927d1d 100644
--- a/platform/darwin/src/MGLMapCamera.h
+++ b/platform/darwin/src/MGLMapCamera.h
@@ -2,12 +2,15 @@
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
An `MGLMapCamera` object represents a viewpoint from which the user observes
some point on an `MGLMapView`.
*/
+MGL_EXPORT
@interface MGLMapCamera : NSObject <NSSecureCoding, NSCopying>
/** Coordinate at the center of the map view. */
@@ -31,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a new camera based on information about the camera’s viewpoint
and focus point.
-
+
@param centerCoordinate The geographic coordinate on which the map should be
centered.
@param eyeCoordinate The geometric coordinate at which the camera should be
@@ -46,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a new camera with the given distance, pitch, and heading.
-
+
@param centerCoordinate The geographic coordinate on which the map should be
centered.
@param distance The straight-line distance from the viewpoint to the
diff --git a/platform/darwin/src/MGLMapCamera.mm b/platform/darwin/src/MGLMapCamera.mm
index 897abab780..613124da66 100644
--- a/platform/darwin/src/MGLMapCamera.mm
+++ b/platform/darwin/src/MGLMapCamera.mm
@@ -25,16 +25,16 @@ BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
{
mbgl::LatLng centerLatLng = mbgl::LatLng(centerCoordinate.latitude, centerCoordinate.longitude);
mbgl::LatLng eyeLatLng = mbgl::LatLng(eyeCoordinate.latitude, eyeCoordinate.longitude);
-
+
mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng);
mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng);
CLLocationDirection heading = std::atan((centerMeters.northing - eyeMeters.northing) /
(centerMeters.easting - eyeMeters.easting));
-
+
double groundDistance = std::hypot(centerMeters.northing - eyeMeters.northing,
centerMeters.easting - eyeMeters.easting);
CGFloat pitch = std::atan(eyeAltitude / groundDistance);
-
+
return [[self alloc] initWithCenterCoordinate:centerCoordinate
altitude:eyeAltitude
pitch:pitch
@@ -113,7 +113,7 @@ BOOL MGLEqualFloatWithAccuracy(CGFloat left, CGFloat right, CGFloat accuracy)
{
return YES;
}
-
+
MGLMapCamera *otherCamera = other;
return (_centerCoordinate.latitude == otherCamera.centerCoordinate.latitude
&& _centerCoordinate.longitude == otherCamera.centerCoordinate.longitude
diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h
index f083a5bec4..ca08e5405a 100644
--- a/platform/darwin/src/MGLMultiPoint.h
+++ b/platform/darwin/src/MGLMultiPoint.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLShape.h"
NS_ASSUME_NONNULL_BEGIN
@@ -8,20 +9,21 @@ NS_ASSUME_NONNULL_BEGIN
/**
The `MGLMultiPoint` class is an abstract superclass used to define shapes
composed of multiple vertices.
-
+
You do not create instances of this class directly. Instead, you create
instances of the `MGLPolyline` or `MGLPolygon` classes. However, you can use
the method and properties of this class to access information about the
vertices of the line or polygon.
-
+
Do not confuse `MGLMultiPoint` with `MGLPointCollection`, which represents a
collection of related but disconnected points.
*/
+MGL_EXPORT
@interface MGLMultiPoint : MGLShape
/**
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
@@ -34,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Retrieves the vertices of part of the shape.
-
+
@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.
@@ -48,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Sets the shape’s vertices to the given C array of vertices.
-
+
@param coords The array of coordinates defining 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.
@@ -58,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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 `coordinates` property.
@param count The number of items in the `coords` array.
@@ -70,7 +72,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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 shape’s `coordinates` property.
@param count The number of items in the `coords` array.
@@ -81,15 +83,15 @@ NS_ASSUME_NONNULL_BEGIN
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
@@ -103,15 +105,15 @@ NS_ASSUME_NONNULL_BEGIN
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
@@ -128,10 +130,10 @@ NS_ASSUME_NONNULL_BEGIN
/**
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
diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm
index 3b03b78ca6..8e8c5be304 100644
--- a/platform/darwin/src/MGLMultiPoint.mm
+++ b/platform/darwin/src/MGLMultiPoint.mm
@@ -44,7 +44,7 @@
{
if (self == other) return YES;
if (![other isKindOfClass:[MGLMultiPoint class]]) return NO;
-
+
MGLMultiPoint *otherMultipoint = other;
return ([super isEqual:otherMultipoint]
&& _coordinates == otherMultipoint->_coordinates);
@@ -97,7 +97,7 @@
[NSException raise:NSInvalidArgumentException
format:@"A multipoint must have at least one vertex."];
}
-
+
[self willChangeValueForKey:@"coordinates"];
_coordinates = { coords, coords + count };
_bounds = {};
@@ -108,13 +108,13 @@
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 = {};
@@ -135,7 +135,7 @@
if (!count && !range.length) {
return;
}
-
+
if (NSMaxRange(range) > _coordinates.size()) {
[NSException raise:NSRangeException
format:@"Invalid range %@ for existing coordinate count %ld",
diff --git a/platform/darwin/src/MGLNetworkConfiguration.h b/platform/darwin/src/MGLNetworkConfiguration.h
index 88fb07e111..644291ee13 100644
--- a/platform/darwin/src/MGLNetworkConfiguration.h
+++ b/platform/darwin/src/MGLNetworkConfiguration.h
@@ -3,11 +3,11 @@
NS_ASSUME_NONNULL_BEGIN
/**
- The MGLNetworkConfiguration object provides a global way to set a base API URL for
+ The MGLNetworkConfiguration object provides a global way to set a base API URL for
retrieval of map data, styles, and other resources.
-
- Currently, MGLNetworkConfiguration is private API in code but is able to be used
- by any applications via the `MGLMapboxAPIBaseURL` dictionary key in the
+
+ Currently, MGLNetworkConfiguration is private API in code but is able to be used
+ by any applications via the `MGLMapboxAPIBaseURL` dictionary key in the
application's `Info.plist`.
*/
@interface MGLNetworkConfiguration : NSObject
@@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
/// Returns the shared instance of the `MGLNetworkConfiguration` class.
+ (instancetype)sharedManager;
-/// The current API base URL. If `nil`, the Mapbox default base API URL is in use.
+/// The current API base URL. If `nil`, the Mapbox default base API URL is in use.
@property (atomic, nullable) NSURL *apiBaseURL;
@end
diff --git a/platform/darwin/src/MGLOfflinePack.h b/platform/darwin/src/MGLOfflinePack.h
index a741833105..0b2db35b1a 100644
--- a/platform/darwin/src/MGLOfflinePack.h
+++ b/platform/darwin/src/MGLOfflinePack.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLOfflineRegion.h"
NS_ASSUME_NONNULL_BEGIN
@@ -10,20 +11,20 @@ NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM (NSInteger, MGLOfflinePackState) {
/**
It is unknown whether the pack is inactive, active, or complete.
-
+
This is the initial state of a pack. The state of a pack becomes known by
the time the shared `MGLOfflineStorage` object sends the first
`MGLOfflinePackProgressChangedNotification` about the pack. For inactive
packs, you must explicitly request a progress update using the
`-[MGLOfflinePack requestProgress]` method.
-
+
An invalid pack always has a state of `MGLOfflinePackStateInvalid`, never
`MGLOfflinePackStateUnknown`.
*/
MGLOfflinePackStateUnknown = 0,
/**
The pack is incomplete and is not currently downloading.
-
+
This is the initial state of a pack that is created using the
`-[MGLOfflineStorage addPackForRegion:withContext:completionHandler:]`
method, as well as after the `-[MGLOfflinePack suspend]` method is
@@ -32,7 +33,7 @@ typedef NS_ENUM (NSInteger, MGLOfflinePackState) {
MGLOfflinePackStateInactive = 1,
/**
The pack is incomplete and is currently downloading.
-
+
This is the state of a pack after the `-[MGLOfflinePack resume]` method is
called.
*/
@@ -76,7 +77,7 @@ typedef struct MGLOfflinePackProgress {
/**
The minimum number of resources that must be downloaded in order to view
the pack’s full region without any omissions.
-
+
At the beginning of a download, this count is a lower bound; the number of
expected resources may increase as the download progresses.
*/
@@ -84,7 +85,7 @@ typedef struct MGLOfflinePackProgress {
/**
The maximum number of resources that must be downloaded in order to view
the pack’s full region without any omissions.
-
+
At the beginning of a download, when the exact number of required resources
is unknown, this field is set to `UINT64_MAX`. Thus this count is always an
upper bound.
@@ -95,11 +96,12 @@ typedef struct MGLOfflinePackProgress {
/**
An `MGLOfflinePack` represents a collection of resources necessary for viewing
a region offline to a local database.
-
+
To create an instance of `MGLOfflinePack`, use the
`+[MGLOfflineStorage addPackForRegion:withContext:completionHandler:]` method.
A pack created using `-[MGLOfflinePack init]` is immediately invalid.
*/
+MGL_EXPORT
@interface MGLOfflinePack : NSObject
/**
@@ -109,7 +111,7 @@ typedef struct MGLOfflinePackProgress {
/**
Arbitrary data stored alongside the downloaded resources.
-
+
The context typically holds application-specific information for identifying
the pack, such as a user-selected name.
*/
@@ -117,7 +119,7 @@ typedef struct MGLOfflinePackProgress {
/**
The pack’s current state.
-
+
The state of an inactive or completed pack is computed lazily and is set to
`MGLOfflinePackStateUnknown` by default. To request the pack’s status, use the
`-requestProgress` method. To get notified when the state becomes known and
@@ -130,7 +132,7 @@ typedef struct MGLOfflinePackProgress {
/**
The pack’s current progress.
-
+
The progress of an inactive or completed pack is computed lazily, and all its
fields are set to 0 by default. To request the pack’s progress, use the
`-requestProgress` method. To get notified when the progress becomes
@@ -143,33 +145,33 @@ typedef struct MGLOfflinePackProgress {
/**
Resumes downloading if the pack is inactive.
-
+
When a pack resumes after being suspended, it may begin by iterating over the
already downloaded resources. As a result, the `progress` structure’s
`countOfResourcesCompleted` field may revert to 0 before rapidly returning to
the level of progress at the time the pack was suspended.
-
+
To temporarily suspend downloading, call the `-suspend` method.
*/
- (void)resume;
/**
Temporarily stops downloading if the pack is active.
-
+
A pack suspends asynchronously, so some network requests may be sent after this
method is called. Regardless, the `progress` property will not be updated until
`-resume` is called.
-
+
If the pack previously reached a higher level of progress before being
suspended, it may wait to suspend until it returns to that level.
-
+
To resume downloading, call the `-resume` method.
*/
- (void)suspend;
/**
Request an asynchronous update to the pack’s `state` and `progress` properties.
-
+
The state and progress of an inactive or completed pack are computed lazily. If
you need the state or progress of a pack whose `state` property is currently
set to `MGLOfflinePackStateUnknown`, observe KVO change notifications on this
diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm
index 1f2fd95f2b..60a7b55531 100644
--- a/platform/darwin/src/MGLOfflinePack.mm
+++ b/platform/darwin/src/MGLOfflinePack.mm
@@ -4,11 +4,13 @@
#import "MGLOfflineRegion_Private.h"
#import "MGLTilePyramidOfflineRegion.h"
+#import "NSValue+MGLAdditions.h"
+
#include <mbgl/storage/default_file_source.hpp>
/**
Assert that the current offline pack is valid.
-
+
This macro should be used at the beginning of any public-facing instance method
of `MGLOfflinePack`. For private methods, an assertion is more appropriate.
*/
@@ -26,18 +28,17 @@
class MBGLOfflineRegionObserver : public mbgl::OfflineRegionObserver {
public:
MBGLOfflineRegionObserver(MGLOfflinePack *pack_) : pack(pack_) {}
-
+
void statusChanged(mbgl::OfflineRegionStatus status) override;
void responseError(mbgl::Response::Error error) override;
void mapboxTileCountLimitExceeded(uint64_t limit) override;
-
+
private:
__weak MGLOfflinePack *pack = nullptr;
};
@interface MGLOfflinePack ()
-@property (nonatomic, weak, nullable) id <MGLOfflinePackDelegate> delegate;
@property (nonatomic, nullable, readwrite) mbgl::OfflineRegion *mbglOfflineRegion;
@property (nonatomic, readwrite) MGLOfflinePackProgress progress;
@@ -59,7 +60,7 @@ private:
if (self = [super init]) {
_mbglOfflineRegion = region;
_state = MGLOfflinePackStateUnknown;
-
+
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique<MBGLOfflineRegionObserver>(self));
}
@@ -72,7 +73,7 @@ private:
- (id <MGLOfflineRegion>)region {
MGLAssertOfflinePackIsValid();
-
+
const mbgl::OfflineRegionDefinition &regionDefinition = _mbglOfflineRegion->getDefinition();
NSAssert([MGLTilePyramidOfflineRegion conformsToProtocol:@protocol(MGLOfflineRegion_Private)], @"MGLTilePyramidOfflineRegion should conform to MGLOfflineRegion_Private.");
return [(id <MGLOfflineRegion_Private>)[MGLTilePyramidOfflineRegion alloc] initWithOfflineRegionDefinition:regionDefinition];
@@ -80,35 +81,35 @@ private:
- (NSData *)context {
MGLAssertOfflinePackIsValid();
-
+
const mbgl::OfflineRegionMetadata &metadata = _mbglOfflineRegion->getMetadata();
return [NSData dataWithBytes:&metadata[0] length:metadata.size()];
}
- (void)resume {
MGLAssertOfflinePackIsValid();
-
+
self.state = MGLOfflinePackStateActive;
-
+
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active);
}
- (void)suspend {
MGLAssertOfflinePackIsValid();
-
+
if (self.state == MGLOfflinePackStateActive) {
self.state = MGLOfflinePackStateInactive;
_isSuspending = YES;
}
-
+
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive);
}
- (void)invalidate {
NSAssert(_state != MGLOfflinePackStateInvalid, @"Cannot invalidate an already invalid offline pack.");
-
+
self.state = MGLOfflinePackStateInvalid;
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr);
@@ -123,9 +124,9 @@ private:
NSAssert(_state == MGLOfflinePackStateInvalid, @"A valid MGLOfflinePack has no mbgl::OfflineRegion.");
return;
}
-
+
NSAssert(_state != MGLOfflinePackStateInvalid, @"Cannot change the state of an invalid offline pack.");
-
+
if (!_isSuspending || state != MGLOfflinePackStateActive) {
_isSuspending = NO;
_state = state;
@@ -134,9 +135,9 @@ private:
- (void)requestProgress {
MGLAssertOfflinePackIsValid();
-
+
mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource];
-
+
__weak MGLOfflinePack *weakSelf = self;
mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](__unused std::exception_ptr exception, mbgl::optional<mbgl::OfflineRegionStatus> status) {
if (status) {
@@ -151,21 +152,21 @@ private:
- (void)offlineRegionStatusDidChange:(mbgl::OfflineRegionStatus)status {
NSAssert(_state != MGLOfflinePackStateInvalid, @"Cannot change update progress of an invalid offline pack.");
-
+
switch (status.downloadState) {
case mbgl::OfflineRegionDownloadState::Inactive:
self.state = status.complete() ? MGLOfflinePackStateComplete : MGLOfflinePackStateInactive;
break;
-
+
case mbgl::OfflineRegionDownloadState::Active:
self.state = MGLOfflinePackStateActive;
break;
}
-
+
if (_isSuspending) {
return;
}
-
+
MGLOfflinePackProgress progress;
progress.countOfResourcesCompleted = status.completedResourceCount;
progress.countOfBytesCompleted = status.completedResourceSize;
@@ -174,8 +175,30 @@ private:
progress.countOfResourcesExpected = status.requiredResourceCount;
progress.maximumResourcesExpected = status.requiredResourceCountIsPrecise ? status.requiredResourceCount : UINT64_MAX;
self.progress = progress;
-
- [self.delegate offlinePack:self progressDidChange:progress];
+
+ NSDictionary *userInfo = @{MGLOfflinePackUserInfoKeyState: @(self.state),
+ MGLOfflinePackUserInfoKeyProgress: [NSValue valueWithMGLOfflinePackProgress:progress]};
+
+ NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
+ [noteCenter postNotificationName:MGLOfflinePackProgressChangedNotification
+ object:self
+ userInfo:userInfo];
+}
+
+- (void)didReceiveError:(NSError *)error {
+ NSDictionary *userInfo = @{ MGLOfflinePackUserInfoKeyError: error };
+ NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
+ [noteCenter postNotificationName:MGLOfflinePackErrorNotification
+ object:self
+ userInfo:userInfo];
+}
+
+- (void)didReceiveMaximumAllowedMapboxTiles:(uint64_t)limit {
+ NSDictionary *userInfo = @{ MGLOfflinePackUserInfoKeyMaximumCount: @(limit) };
+ NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
+ [noteCenter postNotificationName:MGLOfflinePackMaximumMapboxTilesReachedNotification
+ object:self
+ userInfo:userInfo];
}
NSError *MGLErrorFromResponseError(mbgl::Response::Error error) {
@@ -184,15 +207,15 @@ NSError *MGLErrorFromResponseError(mbgl::Response::Error error) {
case mbgl::Response::Error::Reason::NotFound:
errorCode = MGLErrorCodeNotFound;
break;
-
+
case mbgl::Response::Error::Reason::Server:
errorCode = MGLErrorCodeBadServerResponse;
break;
-
+
case mbgl::Response::Error::Reason::Connection:
errorCode = MGLErrorCodeConnectionFailed;
break;
-
+
default:
break;
}
@@ -211,12 +234,12 @@ void MBGLOfflineRegionObserver::statusChanged(mbgl::OfflineRegionStatus status)
void MBGLOfflineRegionObserver::responseError(mbgl::Response::Error error) {
dispatch_async(dispatch_get_main_queue(), ^{
- [pack.delegate offlinePack:pack didReceiveError:MGLErrorFromResponseError(error)];
+ [pack didReceiveError:MGLErrorFromResponseError(error)];
});
}
void MBGLOfflineRegionObserver::mapboxTileCountLimitExceeded(uint64_t limit) {
dispatch_async(dispatch_get_main_queue(), ^{
- [pack.delegate offlinePack:pack didReceiveMaximumAllowedMapboxTiles:limit];
+ [pack didReceiveMaximumAllowedMapboxTiles:limit];
});
}
diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h
index 95d8ba4323..8a63152dca 100644
--- a/platform/darwin/src/MGLOfflinePack_Private.h
+++ b/platform/darwin/src/MGLOfflinePack_Private.h
@@ -4,19 +4,8 @@
NS_ASSUME_NONNULL_BEGIN
-@protocol MGLOfflinePackDelegate;
-
@interface MGLOfflinePack (Private)
-/**
- The pack’s delegate.
-
- You can use the offline pack delegate to be notified of any changes in the
- pack’s progress and of any errors while downloading. For more information, see
- the `MGLOfflinePackDelegate` documentation.
- */
-@property (nonatomic, weak, nullable) id <MGLOfflinePackDelegate> delegate;
-
@property (nonatomic, nullable) mbgl::OfflineRegion *mbglOfflineRegion;
@property (nonatomic, readwrite) MGLOfflinePackState state;
@@ -31,47 +20,4 @@ NS_ASSUME_NONNULL_BEGIN
@end
-/**
- The `MGLOfflinePackDelegate` protocol defines methods that a delegate of an
- `MGLOfflinePack` object can optionally implement to be notified of any changes
- in the pack’s download progress and of any errors while downloading.
- */
-@protocol MGLOfflinePackDelegate <NSObject>
-
-/**
- Sent whenever the pack’s state or download progress changes. Every change to a
- field in the `progress` property corresponds to an invocation of this method.
-
- @param pack The pack whose state of progress changed.
- @param progress The updated progress. To get the updated state, refer to the
- `state` property.
- */
-- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(MGLOfflinePackProgress)progress;
-
-/**
- Sent whenever the pack encounters an error while downloading.
-
- Download errors may be recoverable. For example, this pack’s implementation may
- attempt to re-request failed resources based on an exponential backoff
- strategy or upon the restoration of network access.
-
- @param pack The pack that encountered an error.
- @param error A download error. For a list of possible error codes, see
- `MGLErrorCode`.
- */
-- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error;
-
-/**
- Sent when the maximum number of Mapbox-hosted tiles has been downloaded and
- stored on the current device.
-
- Once this limit is reached, no instance of `MGLOfflinePack` can download
- additional tiles from Mapbox APIs until already downloaded tiles are removed by
- calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method.
- Contact your Mapbox sales representative to have the limit raised.
- */
-- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount;
-
-@end
-
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLOfflineRegion_Private.h b/platform/darwin/src/MGLOfflineRegion_Private.h
index 22106987d0..b1dec8dd64 100644
--- a/platform/darwin/src/MGLOfflineRegion_Private.h
+++ b/platform/darwin/src/MGLOfflineRegion_Private.h
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Initializes and returns an offline region backed by the given C++ region
definition object.
-
+
@param definition A reference to an offline region definition backing the
offline region.
*/
diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h
index 6e60f26e77..16f134adb1 100644
--- a/platform/darwin/src/MGLOfflineStorage.h
+++ b/platform/darwin/src/MGLOfflineStorage.h
@@ -1,11 +1,13 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@class MGLOfflinePack;
@protocol MGLOfflineRegion;
+@protocol MGLOfflineStorageDelegate;
/**
Posted by the shared `MGLOfflineStorage` object when an `MGLOfflinePack`
@@ -13,19 +15,19 @@ NS_ASSUME_NONNULL_BEGIN
downloaded or because the pack discovers during the download that more
resources are required for offline viewing. This notification is posted
whenever any field in the `progress` property changes.
-
+
The `object` is the `MGLOfflinePack` object whose progress changed. The
`userInfo` dictionary contains the pack’s current state in the
`MGLOfflinePackStateUserInfoKey` key and details about the pack’s current
progress in the `MGLOfflinePackProgressUserInfoKey` key. You may also consult
the `MGLOfflinePack.state` and `MGLOfflinePack.progress` properties, which
provide the same values.
-
+
If you only need to observe changes in a particular pack’s progress, you can
alternatively observe KVO change notifications to the pack’s `progress` key
path.
*/
-extern const NSNotificationName MGLOfflinePackProgressChangedNotification;
+extern MGL_EXPORT const NSNotificationName MGLOfflinePackProgressChangedNotification;
/**
Posted by the shared `MGLOfflineStorage` object whenever an `MGLOfflinePack`
@@ -33,27 +35,27 @@ extern const NSNotificationName MGLOfflinePackProgressChangedNotification;
may not warrant the user’s attention. For example, the pack’s implementation
may attempt to re-request failed resources based on an exponential backoff
strategy or upon the restoration of network access.
-
+
The `object` is the `MGLOfflinePack` object that encountered the error. The
`userInfo` dictionary contains the error object in the
`MGLOfflinePackErrorUserInfoKey` key.
*/
-extern const NSNotificationName MGLOfflinePackErrorNotification;
+extern MGL_EXPORT const NSNotificationName MGLOfflinePackErrorNotification;
/**
Posted by the shared `MGLOfflineStorage` object when the maximum number of
Mapbox-hosted tiles has been downloaded and stored on the current device.
-
+
The `object` is the `MGLOfflinePack` object that reached the tile limit in the
course of downloading. The `userInfo` dictionary contains the tile limit in the
`MGLOfflinePackMaximumCountUserInfoKey` key.
-
+
Once this limit is reached, no instance of `MGLOfflinePack` can download
additional tiles from Mapbox APIs until already downloaded tiles are removed by
calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method.
Contact your Mapbox sales representative to have the limit raised.
*/
-extern const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification;
+extern MGL_EXPORT const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification;
/**
A key in the `userInfo` property of a notification posted by `MGLOfflinePack`.
@@ -66,9 +68,9 @@ typedef NSString *MGLOfflinePackUserInfoKey NS_EXTENSIBLE_STRING_ENUM;
`MGLOfflinePackProgressChangedNotification` notification. Call `-integerValue`
on the object to receive the `MGLOfflinePackState`-typed state.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState;
-extern NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyState")));
+extern MGL_EXPORT NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyState")));
/**
The key for an `NSValue` object that indicates an offline pack’s current
@@ -77,9 +79,9 @@ extern NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated
`-MGLOfflinePackProgressValue` on the object to receive the
`MGLOfflinePackProgress`-typed progress.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress;
-extern NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyProgress")));
+extern MGL_EXPORT NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyProgress")));
/**
The key for an `NSError` object that is encountered in the course of
@@ -87,9 +89,9 @@ extern NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((depreca
an `MGLOfflinePackErrorNotification` notification. The error’s domain is
`MGLErrorDomain`. See `MGLErrorCode` for possible error codes.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError;
-extern NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyError")));
+extern MGL_EXPORT NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyError")));
/**
The key for an `NSNumber` object that indicates the maximum number of
@@ -99,17 +101,17 @@ extern NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated
`-unsignedLongLongValue` on the object to receive the `uint64_t`-typed tile
limit.
*/
-extern const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount;
+extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount;
-extern NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyMaximumCount")));
+extern MGL_EXPORT NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyMaximumCount")));
/**
A block to be called once an offline pack has been completely created and
added.
-
+
An application typically calls the `-resume` method on the pack inside this
completion handler to begin the download.
-
+
@param pack Contains a pointer to the newly added pack, or `nil` if there was
an error creating or adding the pack.
@param error Contains a pointer to an error object (if any) indicating why the
@@ -120,22 +122,47 @@ typedef void (^MGLOfflinePackAdditionCompletionHandler)(MGLOfflinePack * _Nullab
/**
A block to be called once an offline pack has been completely invalidated and
removed.
-
+
Avoid any references to the pack inside this completion handler: by the time
this completion handler is executed, the pack has become invalid, and any
messages passed to it will raise an exception.
-
+
@param error Contains a pointer to an error object (if any) indicating why the
pack could not be invalidated or removed.
*/
typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error);
/**
+ The type of resource that is requested.
+ */
+typedef NS_ENUM(NSUInteger, MGLResourceKind) {
+ /** Unknown type */
+ MGLResourceKindUnknown,
+ /** Style sheet JSON file */
+ MGLResourceKindStyle,
+ /** TileJSON file as specified in https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sources */
+ MGLResourceKindSource,
+ /** A vector or raster tile as described in the style sheet at
+ https://www.mapbox.com/mapbox-gl-js/style-spec/#sources */
+ MGLResourceKindTile,
+ /** Signed distance field glyphs for text rendering. These are the URLs specified in the style
+ in https://www.mapbox.com/mapbox-gl-js/style-spec/#root-glyphs */
+ MGLResourceKindGlyphs,
+ /** Image part of a sprite sheet. It is constructed of the prefix in
+ https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sprite and a PNG file extension. */
+ MGLResourceKindSpriteImage,
+ /** JSON part of a sprite sheet. It is constructed of the prefix in
+ https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sprite and a JSON file extension. */
+ MGLResourceKindSpriteJSON,
+};
+
+/**
MGLOfflineStorage implements a singleton (shared object) that manages offline
packs. All of this class’s instance methods are asynchronous, reflecting the
fact that offline resources are stored in a database. The shared object
maintains a canonical collection of offline packs in its `packs` property.
*/
+MGL_EXPORT
@interface MGLOfflineStorage : NSObject
/**
@@ -143,15 +170,29 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
*/
+ (instancetype)sharedOfflineStorage;
+#pragma mark - Accessing the Delegate
+
+/**
+ The receiver’s delegate.
+
+ An offline storage object sends messages to its delegate to allow it to
+ transform URLs before they are requested from the internet. This can be used
+ add or remove custom parameters, or reroute certain requests to other servers
+ or endpoints.
+ */
+@property(nonatomic, weak, nullable) IBOutlet id<MGLOfflineStorageDelegate> delegate;
+
+#pragma mark - Managing Offline Packs
+
/**
An array of all known offline packs, in the order in which they were created.
-
+
This property is set to `nil`, indicating that the receiver does not yet know
the existing packs, for an undefined amount of time starting from the moment
the shared offline storage object is initialized until the packs are fetched
from the database. After that point, this property is always non-nil, but it
may be empty to indicate that no packs are present.
-
+
To detect when the shared offline storage object has finished loading its
`packs` property, observe KVO change notifications on the `packs` key path.
The initial load results in an `NSKeyValueChangeSetting` change.
@@ -161,19 +202,19 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
/**
Creates and registers an offline pack that downloads the resources needed to
use the given region offline.
-
+
The resulting pack is added to the shared offline storage object’s `packs`
property, then the `completion` block is executed with that pack passed in.
-
+
The pack has an initial state of `MGLOfflinePackStateInactive`. To begin
downloading resources, call `-[MGLOfflinePack resume]` on the pack from within
the completion handler. To monitor download progress, add an observer for
`MGLOfflinePackProgressChangedNotification`s about that pack.
-
+
To detect when any call to this method results in a new pack, observe KVO
change notifications on the shared offline storage object’s `packs` key path.
Additions to that array result in an `NSKeyValueChangeInsertion` change.
-
+
@param region A region to download.
@param context Arbitrary data to store alongside the downloaded resources.
@param completion The completion handler to call once the pack has been added.
@@ -184,17 +225,17 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
/**
Unregisters the given offline pack and allows resources that are no longer
required by any remaining packs to be potentially freed.
-
+
As soon as this method is called on a pack, the pack becomes invalid; any
attempt to send it a message will result in an exception being thrown. If an
error occurs and the pack cannot be removed, do not attempt to reuse the pack
object. Instead, if you need continued access to the pack, suspend all packs
and use the `-reloadPacks` method to obtain valid pointers to all the packs.
-
+
To detect when any call to this method results in a pack being removed, observe
KVO change notifications on the shared offline storage object’s `packs` key
path. Removals from that array result in an `NSKeyValueChangeRemoval` change.
-
+
When you remove an offline pack, any resources that are required by that pack,
but not other packs, become eligible for deletion from offline storage. Because
the backing store used for offline storage is also used as a general purpose
@@ -214,9 +255,9 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
`packs` property change, even if the underlying data for these packs has not
changed. If this method is called while a pack is actively downloading, the
behavior is undefined.
-
+
You typically do not need to call this method.
-
+
To detect when the shared offline storage object has finished reloading its
`packs` property, observe KVO change notifications on the `packs` key path.
A reload results in an `NSKeyValueChangeSetting` change.
@@ -226,12 +267,12 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
/**
Sets the maximum number of Mapbox-hosted tiles that may be downloaded and
stored on the current device.
-
+
Once this limit is reached, an
`MGLOfflinePackMaximumMapboxTilesReachedNotification` is posted for every
attempt to download additional tiles until already downloaded tiles are removed
by calling the `-removePack:withCompletionHandler:` method.
-
+
@note The <a href="https://www.mapbox.com/tos/">Mapbox Terms of Service</a>
prohibits changing or bypassing this limit without permission from Mapbox.
Contact your Mapbox sales representative to have the limit raised.
@@ -240,7 +281,7 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
/**
The cumulative size, measured in bytes, of all downloaded resources on disk.
-
+
The returned value includes all resources, including tiles, whether downloaded
as part of an offline pack or due to caching during normal use of `MGLMapView`.
*/
@@ -248,4 +289,25 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error
@end
+/**
+ The `MGLOfflineStorageDelegate` protocol defines methods that a delegate of an
+ `MGLOfflineStorage` object can optionally implement to transform various types
+ of URLs before downloading them via the internet.
+ */
+@protocol MGLOfflineStorageDelegate <NSObject>
+
+/**
+ Sent whenever a URL needs to be transformed.
+
+ @param storage The storage object processing the download.
+ @param kind The kind of URL to be transformed.
+ @param url The original URL to be transformed.
+ @return A URL that will now be downloaded.
+ */
+- (NSURL *)offlineStorage:(MGLOfflineStorage *)storage
+ URLForResourceOfKind:(MGLResourceKind)kind
+ withURL:(NSURL *)url;
+
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 10acc58b25..64f9111f14 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -26,7 +26,7 @@ NSString * const MGLOfflinePackErrorUserInfoKey = MGLOfflinePackUserInfoKeyError
const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount = @"MaximumCount";
NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoKeyMaximumCount;
-@interface MGLOfflineStorage () <MGLOfflinePackDelegate>
+@interface MGLOfflineStorage ()
@property (nonatomic, strong, readwrite) NS_MUTABLE_ARRAY_OF(MGLOfflinePack *) *packs;
@property (nonatomic) mbgl::DefaultFileSource *mbglFileSource;
@@ -42,9 +42,53 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
sharedOfflineStorage = [[self alloc] init];
[sharedOfflineStorage reloadPacks];
});
+
return sharedOfflineStorage;
}
+- (void)setDelegate:(id<MGLOfflineStorageDelegate>)newValue {
+ _delegate = newValue;
+ if ([self.delegate respondsToSelector:@selector(offlineStorage:URLForResourceOfKind:withURL:)]) {
+ _mbglFileSource->setResourceTransform([offlineStorage = self](auto kind_, std::string&& url_) -> std::string {
+ NSURL* url =
+ [NSURL URLWithString:[[NSString alloc] initWithBytes:url_.data()
+ length:url_.length()
+ encoding:NSUTF8StringEncoding]];
+ MGLResourceKind kind = MGLResourceKindUnknown;
+ switch (kind_) {
+ case mbgl::Resource::Kind::Tile:
+ kind = MGLResourceKindTile;
+ break;
+ case mbgl::Resource::Kind::Glyphs:
+ kind = MGLResourceKindGlyphs;
+ break;
+ case mbgl::Resource::Kind::Style:
+ kind = MGLResourceKindStyle;
+ break;
+ case mbgl::Resource::Kind::Source:
+ kind = MGLResourceKindSource;
+ break;
+ case mbgl::Resource::Kind::SpriteImage:
+ kind = MGLResourceKindSpriteImage;
+ break;
+ case mbgl::Resource::Kind::SpriteJSON:
+ kind = MGLResourceKindSpriteJSON;
+ break;
+ case mbgl::Resource::Kind::Unknown:
+ kind = MGLResourceKindUnknown;
+ break;
+
+ }
+ url = [offlineStorage.delegate offlineStorage:offlineStorage
+ URLForResourceOfKind:kind
+ withURL:url];
+ return url.absoluteString.UTF8String;
+ });
+ } else {
+ _mbglFileSource->setResourceTransform(nullptr);
+ }
+}
+
/**
Returns the file URL to the offline cache, with the option to omit the private
subdirectory for legacy (v3.2.0 - v3.2.3) migration purposes.
@@ -161,11 +205,11 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
- (void)dealloc {
[[MGLNetworkConfiguration sharedManager] removeObserver:self forKeyPath:@"apiBaseURL"];
[[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"];
-
+
for (MGLOfflinePack *pack in self.packs) {
[pack invalidate];
}
-
+
delete _mbglFileSource;
_mbglFileSource = nullptr;
}
@@ -197,7 +241,6 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
pack.state = MGLOfflinePackStateInactive;
MGLOfflineStorage *strongSelf = weakSelf;
[[strongSelf mutableArrayValueForKey:@"packs"] addObject:pack];
- pack.delegate = strongSelf;
if (completion) {
completion(pack, error);
}
@@ -210,7 +253,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
@"Regions of type %@ are unsupported.", NSStringFromClass([region class])];
return;
}
-
+
const mbgl::OfflineTilePyramidRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition];
mbgl::OfflineRegionMetadata metadata(context.length);
[context getBytes:&metadata[0] length:metadata.size()];
@@ -247,7 +290,7 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
completion(nil);
return;
}
-
+
self.mbglFileSource->deleteOfflineRegion(std::move(*mbglOfflineRegion), [&, completion](std::exception_ptr exception) {
NSError *error;
if (exception) {
@@ -269,10 +312,6 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
[pack invalidate];
}
self.packs = [packs mutableCopy];
-
- for (MGLOfflinePack *pack in packs) {
- pack.delegate = self;
- }
}];
}
@@ -312,30 +351,9 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
if (!cachePath) {
return 0;
}
-
+
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:cachePath error:NULL];
return attributes.fileSize;
}
-#pragma mark MGLOfflinePackDelegate methods
-
-- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(__unused MGLOfflinePackProgress)progress {
- [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackProgressChangedNotification object:pack userInfo:@{
- MGLOfflinePackUserInfoKeyState: @(pack.state),
- MGLOfflinePackUserInfoKeyProgress: [NSValue valueWithMGLOfflinePackProgress:progress],
- }];
-}
-
-- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error {
- [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackErrorNotification object:pack userInfo:@{
- MGLOfflinePackUserInfoKeyError: error,
- }];
-}
-
-- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount {
- [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackMaximumMapboxTilesReachedNotification object:pack userInfo:@{
- MGLOfflinePackUserInfoKeyMaximumCount: @(maximumCount),
- }];
-}
-
@end
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h
index f395484436..de4fc92b17 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.h
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLStyleLayer.h"
@@ -14,8 +15,10 @@ typedef struct MGLStyleLayerDrawingContext {
double zoomLevel;
CLLocationDirection direction;
CGFloat pitch;
+ CGFloat fieldOfView;
} MGLStyleLayerDrawingContext;
+MGL_EXPORT
@interface MGLOpenGLStyleLayer : MGLStyleLayer
@property (nonatomic, weak, readonly) MGLMapView *mapView;
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm
index 12986f64c1..da131b6de8 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.mm
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm
@@ -4,13 +4,14 @@
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/math/wrap.hpp>
/**
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.
*/
@@ -22,7 +23,7 @@ void MGLPrepareCustomStyleLayer(void *context) {
/**
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.
*/
@@ -34,6 +35,7 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender
.zoomLevel = params.zoom,
.direction = mbgl::util::wrap(params.bearing, 0., 360.),
.pitch = static_cast<CGFloat>(params.pitch),
+ .fieldOfView = static_cast<CGFloat>(params.fieldOfView),
};
[layer drawInMapView:layer.mapView withContext:drawingContext];
}
@@ -41,7 +43,7 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender
/**
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.
*/
@@ -53,18 +55,18 @@ void MGLFinishCustomStyleLayer(void *context) {
/**
An `MGLOpenGLStyleLayer` is a style layer that is rendered by OpenGL code that
you provide.
-
+
By default, this class does nothing. You can subclass this class to provide
custom OpenGL drawing code that is run on each frame of the map. Your subclass
should override the `-didMoveToMapView:`, `-willMoveFromMapView:`, and
`-drawInMapView:withContext:` methods.
-
+
You can access an existing OpenGL style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new OpenGL style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
@warning This API is undocumented and therefore unsupported. It may change at
any time without notice.
*/
@@ -74,7 +76,7 @@ void MGLFinishCustomStyleLayer(void *context) {
/**
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`.
*/
@@ -88,11 +90,11 @@ void MGLFinishCustomStyleLayer(void *context) {
/**
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.
@@ -152,58 +154,58 @@ void MGLFinishCustomStyleLayer(void *context) {
/**
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 <var>z</var> 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 {
-
+
}
/**
diff --git a/platform/darwin/src/MGLOverlay.h b/platform/darwin/src/MGLOverlay.h
index cc32bad1e6..462a0c1031 100644
--- a/platform/darwin/src/MGLOverlay.h
+++ b/platform/darwin/src/MGLOverlay.h
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
both a point and an area on a map. Overlay objects are essentially data objects
that contain the geographic data needed to represent the map area. Overlays can
take the form of a polyline or polygon.
-
+
You use overlays to layer more sophisticated content on top of a map view. For
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
@@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
The cooordinate rectangle that encompasses the overlay. (required) (read-only)
-
+
This property contains the smallest rectangle that completely encompasses the
overlay. Implementers of this protocol must set this area when implementing
their overlay class, and after setting it, you must not change it.
@@ -36,11 +36,11 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a Boolean indicating whether the specified rectangle intersects the
receiver’s shape.
-
+
You can implement this method to provide more specific bounds checking for an
overlay. If you do not implement it, the bounding rectangle is used to detect
intersections.
-
+
@param overlayBounds The rectangle to intersect with the receiver’s area.
@return `YES` if any part of the map rectangle intersects the receiver’s shape
or `NO` if it does not.
diff --git a/platform/darwin/src/MGLPointAnnotation.h b/platform/darwin/src/MGLPointAnnotation.h
index 969f8c91e7..1ef0962f99 100644
--- a/platform/darwin/src/MGLPointAnnotation.h
+++ b/platform/darwin/src/MGLPointAnnotation.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLShape.h"
NS_ASSUME_NONNULL_BEGIN
@@ -11,12 +12,12 @@ NS_ASSUME_NONNULL_BEGIN
`MGLPointAnnotation` object is known as a point annotation or point shape. For
example, you could use a point shape to represent a city at low zoom levels, an
address at high zoom levels, or the location of a long press gesture.
-
+
You can add point shapes to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s point shapes collectively using an `MGLCircleStyleLayer` or
`MGLSymbolStyleLayer` object.
-
+
For more interactivity, add a selectable point annotation to a map view using
the `-[MGLMapView addAnnotation:]` method. Alternatively, define your own model
class that conforms to the `MGLAnnotation` protocol. Configure a point
@@ -25,14 +26,15 @@ NS_ASSUME_NONNULL_BEGIN
`-[MGLMapViewDelegate mapView:viewForAnnotation:]` (iOS only). A point
annotation’s `MGLShape.title` and `MGLShape.subtitle` properties define the
default content of the annotation’s callout (on iOS) or popover (on macOS).
-
+
To group multiple related points together in one shape, use an
`MGLPointCollection` or `MGLShapeCollection` object.
-
+
A point shape is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.2">Point</a> geometry
in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPointAnnotation : MGLShape
/**
diff --git a/platform/darwin/src/MGLPointAnnotation.mm b/platform/darwin/src/MGLPointAnnotation.mm
index a2108a9e3b..5fd3e25991 100644
--- a/platform/darwin/src/MGLPointAnnotation.mm
+++ b/platform/darwin/src/MGLPointAnnotation.mm
@@ -33,7 +33,7 @@
{
if (other == self) return YES;
if (![other isKindOfClass:[MGLPointAnnotation class]]) return NO;
-
+
MGLPointAnnotation *otherAnnotation = other;
return ([super isEqual:other]
&& self.coordinate.latitude == otherAnnotation.coordinate.latitude
diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h
index 9e14161aed..74b30385a0 100644
--- a/platform/darwin/src/MGLPointCollection.h
+++ b/platform/darwin/src/MGLPointCollection.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLOverlay.h"
#import "MGLShape.h"
@@ -10,28 +11,29 @@
points in the collection may be related but are not connected spatially. For
example, you could use a point collection to represent all the trees in an
orchard.
-
+
You can add point collections to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s point collections collectively using an
`MGLCircleStyleLayer` or `MGLSymbolStyleLayer` object.
-
+
You cannot add an `MGLPointCollection` object directly to a map view as an
annotation. However, you can create individual `MGLPointAnnotation` objects
from the `coordinates` array and add those annotation objects to the map view
using the `-[MGLMapView addAnnotations:]` method.
-
+
A point collection is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.3">MultiPoint</a>
geometry in GeoJSON. Do not confuse `MGLPointCollection` with `MGLMultiPoint`,
the abstract superclass of `MGLPolyline` and `MGLPolygon`.
*/
+MGL_EXPORT
@interface MGLPointCollection : MGLShape <MGLOverlay>
/**
Creates and returns a `MGLPointCollection` object from the specified set of
coordinates.
-
+
@param coords The array of coordinates defining the shape. The data in this
array is copied to the new object.
@param count The number of items in the `coords` array.
@@ -47,7 +49,7 @@
/**
Retrieves one or more coordinates associated with 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.
diff --git a/platform/darwin/src/MGLPointCollection.mm b/platform/darwin/src/MGLPointCollection.mm
index acd78b8b33..ac4aaed60c 100644
--- a/platform/darwin/src/MGLPointCollection.mm
+++ b/platform/darwin/src/MGLPointCollection.mm
@@ -44,7 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)isEqual:(id)other {
if (self == other) return YES;
if (![other isKindOfClass:[MGLPointCollection class]]) return NO;
-
+
MGLPointCollection *otherCollection = (MGLPointCollection *)other;
return ([super isEqual:other]
&& ((![self geoJSONDictionary] && ![otherCollection geoJSONDictionary]) || [[self geoJSONDictionary] isEqualToDictionary:[otherCollection geoJSONDictionary]]));
@@ -112,7 +112,7 @@ NS_ASSUME_NONNULL_BEGIN
CLLocationCoordinate2D coordinate = self.coordinates[index];
[coordinates addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
}
-
+
return @{@"type": @"MultiPoint",
@"coordinates": coordinates};
}
diff --git a/platform/darwin/src/MGLPolygon+MGLAdditions.m b/platform/darwin/src/MGLPolygon+MGLAdditions.m
index def4687016..3e76a37157 100644
--- a/platform/darwin/src/MGLPolygon+MGLAdditions.m
+++ b/platform/darwin/src/MGLPolygon+MGLAdditions.m
@@ -4,14 +4,14 @@
- (NS_ARRAY_OF(id) *)mgl_coordinates {
NSMutableArray *coordinates = [NSMutableArray array];
-
+
NSMutableArray *exteriorRing = [NSMutableArray array];
for (NSUInteger index = 0; index < self.pointCount; index++) {
CLLocationCoordinate2D coordinate = self.coordinates[index];
[exteriorRing addObject:@[@(coordinate.longitude), @(coordinate.latitude)]];
}
[coordinates addObject:exteriorRing];
-
+
for (MGLPolygon *interiorPolygon in self.interiorPolygons) {
NSMutableArray *interiorRing = [NSMutableArray array];
for (int index = 0; index < interiorPolygon.pointCount; index++) {
@@ -20,7 +20,7 @@
}
[coordinates addObject:interiorRing];
}
-
+
return [coordinates copy];
}
diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h
index 674c006095..3fcc1be76d 100644
--- a/platform/darwin/src/MGLPolygon.h
+++ b/platform/darwin/src/MGLPolygon.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
@@ -13,25 +14,25 @@ NS_ASSUME_NONNULL_BEGIN
vertices, specified as `CLLocationCoordinate2D` instances, and the edges that
connect them. For example, you could use a polygon shape to represent a
building, a lake, or an area you want to highlight.
-
+
You can add polygon shapes to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s polygons collectively using an `MGLFillStyleLayer` or
`MGLSymbolStyleLayer` object.
-
+
Alternatively, you can add a polygon overlay directly to a map view using the
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]` method. Configure
a polygon overlay’s appearance using
`-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` and
`-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`.
-
+
The vertices are automatically connected in the order in which you provide
them. You should close the polygon by specifying the same
`CLLocationCoordinate2D` as the first and last vertices; otherwise, the
polygon’s fill may not cover the area you expect it to. To avoid filling the
space within the shape, give the polygon a transparent fill or use an
`MGLPolyline` object.
-
+
A polygon may have one or more interior polygons, or holes, that you specify as
`MGLPolygon` objects with the `+polygonWithCoordinates:count:interiorPolygons:`
method. For example, if a polygon represents a lake, it could exclude an island
@@ -39,19 +40,20 @@ NS_ASSUME_NONNULL_BEGIN
have interior polygons. To represent a shape that includes a polygon within a
hole or, more generally, to group multiple polygons together in one shape, use
an `MGLMultiPolygon` or `MGLShapeCollection` object.
-
+
To make the polygon straddle the antimeridian, specify some longitudes less
than −180 degrees or greater than 180 degrees.
*/
+MGL_EXPORT
@interface MGLPolygon : MGLMultiPoint <MGLOverlay>
/**
The array of polygons nested inside the receiver.
-
+
The area occupied by any interior polygons is excluded from the overall shape.
Interior polygons should not overlap. An interior polygon should not have
interior polygons of its own.
-
+
If there are no interior polygons, the value of this property is `nil`.
*/
@property (nonatomic, nullable, readonly) NS_ARRAY_OF(MGLPolygon *) *interiorPolygons;
@@ -59,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates and returns an `MGLPolygon` object from the specified set of
coordinates.
-
+
@param coords The array of coordinates defining the shape. The data in this
array is copied to the new object.
@param count The number of items in the `coords` array.
@@ -70,7 +72,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates and returns an `MGLPolygon` object from the specified set of
coordinates and interior polygons.
-
+
@param coords The array of coordinates defining the shape. The data in this
array is copied to the new object.
@param count The number of items in the `coords` array.
@@ -90,16 +92,17 @@ NS_ASSUME_NONNULL_BEGIN
atoll: the inner island would be one `MGLPolygon` object, while the surrounding
atoll would be another. You could also use a multipolygon shape to represent a
group of disconnected but related buildings.
-
+
You can add multipolygon shapes to the map by adding them to an
`MGLShapeSource` object. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s multipolygons collectively using an `MGLFillStyleLayer` or
`MGLSymbolStyleLayer` object.
-
+
You cannot add an `MGLMultiPolygon` object directly to a map view using
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can
add the `polygons` array’s items as overlays individually.
*/
+MGL_EXPORT
@interface MGLMultiPolygon : MGLShape <MGLOverlay>
/**
@@ -109,7 +112,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates and returns a multipolygon object consisting of the given polygons.
-
+
@param polygons The array of polygons defining the shape.
@return A new multipolygon object.
*/
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index 565de017cc..ceafe873bf 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -44,7 +44,7 @@
- (BOOL)isEqual:(id)other {
if (self == other) return YES;
if (![other isKindOfClass:[MGLPolygon class]]) return NO;
-
+
MGLPolygon *otherPolygon = (MGLPolygon *)other;
return ([super isEqual:otherPolygon] &&
[[self geoJSONDictionary] isEqualToDictionary:[otherPolygon geoJSONDictionary]]);
@@ -80,7 +80,7 @@
}
- (mbgl::Annotation)annotationObjectWithDelegate:(id <MGLMultiPointDelegate>)delegate {
-
+
mbgl::FillAnnotation annotation { [self polygon] };
annotation.opacity = { static_cast<float>([delegate alphaForShapeAnnotation:self]) };
annotation.outlineColor = { [delegate strokeColorForShapeAnnotation:self] };
@@ -115,9 +115,9 @@
- (instancetype)initWithPolygons:(NS_ARRAY_OF(MGLPolygon *) *)polygons {
if (self = [super init]) {
_polygons = polygons;
-
+
mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
-
+
for (MGLPolygon *polygon in _polygons) {
bounds.extend(MGLLatLngBoundsFromCoordinateBounds(polygon.overlayBounds));
}
@@ -141,7 +141,7 @@
- (BOOL)isEqual:(id)other {
if (self == other) return YES;
if (![other isKindOfClass:[MGLMultiPolygon class]]) return NO;
-
+
MGLMultiPolygon *otherMultiPolygon = other;
return [super isEqual:other]
&& [self.polygons isEqualToArray:otherMultiPolygon.polygons];
diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h
index 429ba9cddc..b3db0fd39f 100644
--- a/platform/darwin/src/MGLPolyline.h
+++ b/platform/darwin/src/MGLPolyline.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import "MGLFoundation.h"
#import "MGLMultiPoint.h"
#import "MGLOverlay.h"
@@ -13,38 +14,39 @@ NS_ASSUME_NONNULL_BEGIN
specified as `CLLocationCoordinate2D` instances, and the line segments that
connect them. For example, you could use an polyline to represent a road or the
path along which something moves.
-
+
You can add polyline shapes to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s polylines collectively using an `MGLLineStyleLayer` or
`MGLSymbolStyleLayer` object.
-
+
Alternatively, you can add a polyline overlay directly to a map view using the
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]` method. Configure
a polyline overlay’s appearance using
`-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` and
`-[MGLMapViewDelegate mapView:lineWidthForPolylineAnnotation:]`.
-
+
The vertices are automatically connected in the order in which you provide
them. The first and last vertices are not connected to each other, but you can
specify the same `CLLocationCoordinate2D` as the first and last vertices in
order to close the polyline. To fill the space within the shape, use an
`MGLPolygon` object. To group multiple polylines together in one shape, use an
`MGLMultiPolyline` or `MGLShapeCollection` object.
-
+
To make the polyline straddle the antimeridian, specify some longitudes less
than −180 degrees or greater than 180 degrees.
-
+
A polyline is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.4">LineString</a>
geometry in GeoJSON.
*/
+MGL_EXPORT
@interface MGLPolyline : MGLMultiPoint <MGLOverlay>
/**
Creates and returns an `MGLPolyline` object from the specified set of
coordinates.
-
+
@param coords The array of coordinates defining the shape. The data in this
array is copied to the new object.
@param count The number of items in the `coords` array.
@@ -59,20 +61,21 @@ NS_ASSUME_NONNULL_BEGIN
polylines. For example, you could use a multipolyline shape to represent both
sides of a divided highway (dual carriageway), excluding the median (central
reservation): each carriageway would be a distinct `MGLPolyline` object.
-
+
You can add multipolyline shapes to the map by adding them to an
`MGLShapeSource` object. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s multipolylines collectively using an `MGLLineStyleLayer` or
`MGLSymbolStyleLayer` object.
-
+
You cannot add an `MGLMultiPolyline` object directly to a map view using
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can
add the `polylines` array’s items as overlays individually.
-
+
A multipolyline is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.5">MultiLineString</a>
geometry in GeoJSON.
*/
+MGL_EXPORT
@interface MGLMultiPolyline : MGLShape <MGLOverlay>
/**
@@ -82,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates and returns a multipolyline object consisting of the given polylines.
-
+
@param polylines The array of polylines defining the shape.
@return A new multipolyline object.
*/
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index e6b1cdebf6..454a1b964b 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -20,13 +20,13 @@
- (mbgl::LineString<double>)lineString {
NSUInteger count = self.pointCount;
CLLocationCoordinate2D *coordinates = self.coordinates;
-
+
mbgl::LineString<double> geometry;
geometry.reserve(self.pointCount);
for (NSUInteger i = 0; i < count; i++) {
geometry.push_back(mbgl::Point<double>(coordinates[i].longitude, coordinates[i].latitude));
}
-
+
return geometry;
}
@@ -69,9 +69,9 @@
- (instancetype)initWithPolylines:(NS_ARRAY_OF(MGLPolyline *) *)polylines {
if (self = [super init]) {
_polylines = polylines;
-
+
mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
-
+
for (MGLPolyline *polyline in _polylines) {
bounds.extend(MGLLatLngBoundsFromCoordinateBounds(polyline.overlayBounds));
}
@@ -96,7 +96,7 @@
{
if (self == other) return YES;
if (![other isKindOfClass:[MGLMultiPolyline class]]) return NO;
-
+
MGLMultiPolyline *otherMultipoline = other;
return ([super isEqual:otherMultipoline]
&& [self.polylines isEqualToArray:otherMultipoline.polylines]);
@@ -127,7 +127,7 @@
NSMutableArray *coordinates = [NSMutableArray array];
for (MGLPolylineFeature *feature in self.polylines) {
[coordinates addObject: feature.mgl_coordinates];
- }
+ }
return @{@"type": @"MultiLineString",
@"coordinates": coordinates};
}
diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h
index c2807c8d2e..694a818246 100644
--- a/platform/darwin/src/MGLRasterSource.h
+++ b/platform/darwin/src/MGLRasterSource.h
@@ -1,7 +1,8 @@
-#import "MGLTileSource.h"
-
#import <CoreGraphics/CoreGraphics.h>
+#import "MGLFoundation.h"
+#import "MGLTileSource.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -9,16 +10,16 @@ NS_ASSUME_NONNULL_BEGIN
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.
-
+
The default value for this option is 512. Version 4 of the
<a href="https://www.mapbox.com/api-documentation/#maps">Mapbox Maps API</a>
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.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionTileSize;
/**
`MGLRasterSource` is a map content source that supplies raster image tiles to
@@ -28,16 +29,16 @@ extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
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
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-raster"><code>raster</code></a>
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:]`.
-
+
### Example
-
+
```swift
let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
@@ -50,27 +51,28 @@ extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
mapView.style?.addSource(source)
```
*/
+MGL_EXPORT
@interface MGLRasterSource : MGLTileSource
#pragma mark Initializing a Source
/**
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://<mapid>`). The URL should
point to a JSON file that conforms to the
<a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>.
-
+
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 configurationURL A URL to a TileJSON configuration file describing the
@@ -82,15 +84,15 @@ extern const MGLTileSourceOption MGLTileSourceOptionTileSize;
/**
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://<mapid>`). The URL should
point to a JSON file that conforms to the
<a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>.
-
+
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param configurationURL A URL to a TileJSON configuration file describing the
diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm
index b52b4e3eed..ccd5212b2a 100644
--- a/platform/darwin/src/MGLRasterSource.mm
+++ b/platform/darwin/src/MGLRasterSource.mm
@@ -5,7 +5,7 @@
#import "MGLTileSource_Private.h"
#import "NSURL+MGLAdditions.h"
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/style/sources/raster_source.hpp>
const MGLTileSourceOption MGLTileSourceOptionTileSize = @"MGLTileSourceOptionTileSize";
@@ -50,7 +50,7 @@ static const CGFloat MGLRasterSourceRetinaTileSize = 512;
- (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options {
if (self = [super initWithIdentifier:identifier tileURLTemplates:tileURLTemplates options:options]) {
mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options);
-
+
uint16_t tileSize = MGLRasterSourceRetinaTileSize;
if (NSNumber *tileSizeNumber = options[MGLTileSourceOptionTileSize]) {
if (![tileSizeNumber isKindOfClass:[NSNumber class]]) {
@@ -59,7 +59,7 @@ static const CGFloat MGLRasterSourceRetinaTileSize = 512;
}
tileSize = static_cast<uint16_t>(round(tileSizeNumber.doubleValue));
}
-
+
auto source = std::make_unique<mbgl::style::RasterSource>(identifier.UTF8String, tileSet, tileSize);
_pendingSource = std::move(source);
self.rawSource = _pendingSource.get();
diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h
index 736e8ee2f5..9e876a6e3c 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.h
+++ b/platform/darwin/src/MGLRasterStyleLayer.h
@@ -1,6 +1,7 @@
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLForegroundStyleLayer.h"
@@ -17,21 +18,22 @@ NS_ASSUME_NONNULL_BEGIN
set</a> uploaded to Mapbox Studio, or a raster map authored in <a
href="https://tilemill-project.github.io/tilemill/">TileMill</a>, the classic
Mapbox Editor, or Mapbox Studio Classic.
-
+
You can access an existing raster style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new raster style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
### Example
-
+
```swift
let layer = MGLRasterStyleLayer(identifier: "clouds", source: source)
layer.rasterOpacity = MGLStyleValue(rawValue: 0.5)
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLRasterStyleLayer : MGLForegroundStyleLayer
#pragma mark - Accessing the Paint Attributes
@@ -47,6 +49,13 @@ NS_ASSUME_NONNULL_BEGIN
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-raster-brightness-max"><code>raster-brightness-max</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *maximumRasterBrightness;
@@ -63,6 +72,13 @@ NS_ASSUME_NONNULL_BEGIN
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-raster-brightness-min"><code>raster-brightness-min</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *minimumRasterBrightness;
@@ -74,6 +90,13 @@ NS_ASSUME_NONNULL_BEGIN
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `0`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterContrast;
@@ -85,6 +108,13 @@ NS_ASSUME_NONNULL_BEGIN
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `300`. Set this property to `nil` to
reset it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterFadeDuration;
@@ -100,6 +130,13 @@ NS_ASSUME_NONNULL_BEGIN
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-raster-hue-rotate"><code>raster-hue-rotate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterHueRotation;
@@ -111,6 +148,13 @@ NS_ASSUME_NONNULL_BEGIN
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `1`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterOpacity;
@@ -120,6 +164,13 @@ NS_ASSUME_NONNULL_BEGIN
The default value of this property is an `MGLStyleValue` object containing an
`NSNumber` object containing the float `0`. Set this property to `nil` to reset
it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterSaturation;
diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm
index 22e182df61..d633bec435 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.mm
+++ b/platform/darwin/src/MGLRasterStyleLayer.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,6 +8,7 @@
#import "MGLStyleValue_Private.h"
#import "MGLRasterStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
@interface MGLRasterStyleLayer ()
@@ -44,7 +45,7 @@
- (NSString *)sourceIdentifier
{
MGLAssertStyleLayerIsValid();
-
+
return @(self.rawLayer->getSourceID().c_str());
}
@@ -92,14 +93,17 @@
- (void)setMaximumRasterBrightness:(MGLStyleValue<NSNumber *> *)maximumRasterBrightness {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(maximumRasterBrightness);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(maximumRasterBrightness);
self.rawLayer->setRasterBrightnessMax(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)maximumRasterBrightness {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterBrightnessMax() ?: self.rawLayer->getDefaultRasterBrightnessMax();
+ auto propertyValue = self.rawLayer->getRasterBrightnessMax();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterBrightnessMax());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -113,14 +117,17 @@
- (void)setMinimumRasterBrightness:(MGLStyleValue<NSNumber *> *)minimumRasterBrightness {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(minimumRasterBrightness);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(minimumRasterBrightness);
self.rawLayer->setRasterBrightnessMin(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)minimumRasterBrightness {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterBrightnessMin() ?: self.rawLayer->getDefaultRasterBrightnessMin();
+ auto propertyValue = self.rawLayer->getRasterBrightnessMin();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterBrightnessMin());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -134,42 +141,51 @@
- (void)setRasterContrast:(MGLStyleValue<NSNumber *> *)rasterContrast {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterContrast);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(rasterContrast);
self.rawLayer->setRasterContrast(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)rasterContrast {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterContrast() ?: self.rawLayer->getDefaultRasterContrast();
+ auto propertyValue = self.rawLayer->getRasterContrast();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterContrast());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setRasterFadeDuration:(MGLStyleValue<NSNumber *> *)rasterFadeDuration {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterFadeDuration);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(rasterFadeDuration);
self.rawLayer->setRasterFadeDuration(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)rasterFadeDuration {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterFadeDuration() ?: self.rawLayer->getDefaultRasterFadeDuration();
+ auto propertyValue = self.rawLayer->getRasterFadeDuration();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterFadeDuration());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setRasterHueRotation:(MGLStyleValue<NSNumber *> *)rasterHueRotation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterHueRotation);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(rasterHueRotation);
self.rawLayer->setRasterHueRotate(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)rasterHueRotation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterHueRotate() ?: self.rawLayer->getDefaultRasterHueRotate();
+ auto propertyValue = self.rawLayer->getRasterHueRotate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterHueRotate());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -183,28 +199,34 @@
- (void)setRasterOpacity:(MGLStyleValue<NSNumber *> *)rasterOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(rasterOpacity);
self.rawLayer->setRasterOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)rasterOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterOpacity() ?: self.rawLayer->getDefaultRasterOpacity();
+ auto propertyValue = self.rawLayer->getRasterOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterOpacity());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setRasterSaturation:(MGLStyleValue<NSNumber *> *)rasterSaturation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterSaturation);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(rasterSaturation);
self.rawLayer->setRasterSaturation(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)rasterSaturation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getRasterSaturation() ?: self.rawLayer->getDefaultRasterSaturation();
+ auto propertyValue = self.rawLayer->getRasterSaturation();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultRasterSaturation());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
diff --git a/platform/darwin/src/MGLShape.h b/platform/darwin/src/MGLShape.h
index 8dc1b4f1cf..bd8b6152d2 100644
--- a/platform/darwin/src/MGLShape.h
+++ b/platform/darwin/src/MGLShape.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLAnnotation.h"
NS_ASSUME_NONNULL_BEGIN
@@ -8,25 +9,26 @@ NS_ASSUME_NONNULL_BEGIN
`MGLShape` is an abstract class that represents a shape or annotation. Shapes
constitute the content of a map – not only the overlays atop the map, but also
the content that forms the base map.
-
+
You do not create instances of this class directly or create subclasses of this
- class. Instead, you create instances of `MGLPointAnnotation`,
+ class. Instead, you create instances of `MGLPointAnnotation`,
`MGLPointCollection`, `MGLPolyline`, `MGLMultiPolyline`, `MGLPolygon`,
`MGLMultiPolygon`, or `MGLShapeCollection`. The shape classes correspond to the
<a href="https://tools.ietf.org/html/rfc7946#section-3.1">Geometry</a> object
types in the GeoJSON standard, but some have nonstandard names for backwards
compatibility.
-
+
Although you do not create instances of this class directly, you can use its
`+[MGLShape shapeWithData:encoding:error:]` factory method to create one of the
concrete subclasses of `MGLShape` noted above from GeoJSON data.
-
+
You can add shapes to the map by adding them to an `MGLShapeSource` object.
Configure the appearance of an `MGLShapeSource`’s or `MGLVectorSource`’s shapes
collectively using a concrete instance of `MGLVectorStyleLayer`. Alternatively,
you can add some kinds of shapes directly to a map view as annotations or
overlays.
*/
+MGL_EXPORT
@interface MGLShape : NSObject <MGLAnnotation, NSSecureCoding>
#pragma mark Creating a Shape
@@ -34,21 +36,21 @@ NS_ASSUME_NONNULL_BEGIN
/**
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`.
-
+
### Example
-
+
```swift
let url = mainBundle.url(forResource: "amsterdam", withExtension: "geojson")!
let data = try! Data(contentsOf: url)
let feature = try! MGLShape(data: data, encoding: String.Encoding.utf8.rawValue) as! 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
@@ -63,9 +65,9 @@ NS_ASSUME_NONNULL_BEGIN
/**
The title of the shape annotation.
-
+
The default value of this property is `nil`.
-
+
This property is ignored when the shape is used in an `MGLShapeSource`. To name
a shape used in a shape source, create an `MGLFeature` and add an attribute to
the `MGLFeature.attributes` property.
@@ -75,7 +77,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
The subtitle of the shape annotation. The default value of this property is
`nil`.
-
+
This property is ignored when the shape is used in an `MGLShapeSource`. To
provide additional information about a shape used in a shape source, create an
`MGLFeature` and add an attribute to the `MGLFeature.attributes` property.
@@ -86,9 +88,9 @@ NS_ASSUME_NONNULL_BEGIN
/**
The tooltip of the shape annotation.
-
+
The default value of this property is `nil`.
-
+
This property is ignored when the shape is used in an `MGLShapeSource`.
*/
@property (nonatomic, copy, nullable) NSString *toolTip;
@@ -100,7 +102,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
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.
*/
diff --git a/platform/darwin/src/MGLShape.mm b/platform/darwin/src/MGLShape.mm
index 984235fd97..e76e06c7e4 100644
--- a/platform/darwin/src/MGLShape.mm
+++ b/platform/darwin/src/MGLShape.mm
@@ -21,7 +21,7 @@ bool operator==(const CLLocationCoordinate2D lhs, const CLLocationCoordinate2D r
}
return nil;
}
-
+
try {
const auto geojson = mapbox::geojson::parse(string.UTF8String);
return MGLShapeFromGeoJSON(geojson);
@@ -81,7 +81,7 @@ bool operator==(const CLLocationCoordinate2D lhs, const CLLocationCoordinate2D r
{
if (other == self) { return YES; }
id <MGLAnnotation> annotation = other;
-
+
#if TARGET_OS_IPHONE
return ((!_title && ![annotation title]) || [_title isEqualToString:[annotation title]])
&& ((!_subtitle && ![annotation subtitle]) || [_subtitle isEqualToString:[annotation subtitle]]);
diff --git a/platform/darwin/src/MGLShapeCollection.h b/platform/darwin/src/MGLShapeCollection.h
index b0f3e964d4..bb107ee7f0 100644
--- a/platform/darwin/src/MGLShapeCollection.h
+++ b/platform/darwin/src/MGLShapeCollection.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLShape.h"
#import "MGLTypes.h"
@@ -10,28 +11,29 @@ NS_ASSUME_NONNULL_BEGIN
An `MGLShapeCollection` object represents a shape consisting of zero or more
distinct but related shapes that are instances of `MGLShape`. The constituent
shapes can be a mixture of different kinds of shapes.
-
+
`MGLShapeCollection` is most commonly used to add multiple shapes to a single
`MGLShapeSource`. Configure the appearance of an `MGLShapeSource`’s or
`MGLVectorSource`’s shape collection collectively using an
`MGLSymbolStyleLayer` object, or use multiple instances of
`MGLCircleStyleLayer`, `MGLFillStyleLayer`, and `MGLLineStyleLayer` to
configure the appearance of each kind of shape inside the collection.
-
+
You cannot add an `MGLShapeCollection` object directly to a map view as an
annotation. However, you can create individual `MGLPointAnnotation`,
`MGLPolyline`, and `MGLPolygon` objects from the `shapes` array and add those
annotation objects to the map view using the `-[MGLMapView addAnnotations:]`
method.
-
+
To represent a collection of point, polyline, or polygon shapes, it may be more
convenient to use an `MGLPointCollection`, `MGLMultiPolyline`, or
`MGLMultiPolygon` object, respectively.
-
- A shape collection is known as a
- <a href="https://tools.ietf.org/html/rfc7946#section-3.1.8">GeometryCollection</a>
+
+ A shape collection is known as a
+ <a href="https://tools.ietf.org/html/rfc7946#section-3.1.8">GeometryCollection</a>
geometry in GeoJSON.
*/
+MGL_EXPORT
@interface MGLShapeCollection : MGLShape
/**
@@ -41,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates and returns a shape collection consisting of the given shapes.
-
+
@param shapes The array of shapes defining the shape collection. The data in
this array is copied to the new object.
@return A new shape collection object.
diff --git a/platform/darwin/src/MGLShapeCollection.mm b/platform/darwin/src/MGLShapeCollection.mm
index 4b468a1cbb..03cab0043f 100644
--- a/platform/darwin/src/MGLShapeCollection.mm
+++ b/platform/darwin/src/MGLShapeCollection.mm
@@ -32,7 +32,7 @@
- (BOOL)isEqual:(id)other {
if (self == other) return YES;
if (![other isKindOfClass:[MGLShapeCollection class]]) return NO;
-
+
MGLShapeCollection *otherShapeCollection = other;
return [super isEqual:otherShapeCollection]
&& [_shapes isEqualToArray:otherShapeCollection.shapes];
diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h
index 0ab3861aa9..24cdf82bea 100644
--- a/platform/darwin/src/MGLShapeSource.h
+++ b/platform/darwin/src/MGLShapeSource.h
@@ -1,5 +1,6 @@
#import "MGLSource.h"
+#import "MGLFoundation.h"
#import "MGLTypes.h"
#import "MGLShape.h"
@@ -20,21 +21,21 @@ typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;
This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
source property in the Mapbox Style Specification.
-
+
This option only affects point features within a shape source.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionClustered;
+extern MGL_EXPORT 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;
+extern MGL_EXPORT 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
+ 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.
@@ -42,7 +43,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-clusterMaxZoom"><code>clusterMaxZoom</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
/**
An `NSNumber` object containing an integer; specifies the maximum zoom level at
@@ -53,19 +54,19 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForCluster
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-maxzoom"><code>maxzoom</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
+extern MGL_EXPORT 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
+ 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.
This attribute corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-buffer"><code>buffer</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
/**
An `NSNumber` object containing a double; specifies the Douglas-Peucker
@@ -76,7 +77,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-tolerance"><code>tolerance</code></a>
source property in the Mapbox Style Specification.
*/
-extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
`MGLShapeSource` is a map content source that supplies vector shapes to be
@@ -85,7 +86,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
<a href="http://geojson.org/">GeoJSON</a> 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
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson"><code>geojson</code></a>
source defined by the style JSON file is represented at runtime by an
@@ -93,12 +94,12 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
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.
-
+
### Example
-
+
```swift
var coordinates: [CLLocationCoordinate2D] = [
CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42),
@@ -109,6 +110,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
mapView.style?.addSource(source)
```
*/
+MGL_EXPORT
@interface MGLShapeSource : MGLSource
#pragma mark Initializing a Source
@@ -116,7 +118,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
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.
@@ -128,17 +130,17 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
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, or use the
- `-initWithIdentifier:features:options:` or
+ `-initWithIdentifier:features:options:` or
`-initWithIdentifier:shapes:options:` methods.
-
+
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.
@@ -149,7 +151,7 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
Returns a shape source with an identifier, an array of features, and a dictionary
of options for the source.
-
+
Unlike `-initWithIdentifier:shapes:options:`, this method accepts `MGLFeature`
instances, such as `MGLPointFeature` objects, whose attributes you can use when
applying a predicate to `MGLVectorStyleLayer` or configuring a style layer’s
@@ -168,11 +170,11 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
Returns a shape source with an identifier, an array of shapes, and a dictionary of
options for the source.
-
+
Any `MGLFeature` instance passed into this initializer is treated as an ordinary
shape, causing any attributes to be inaccessible to an `MGLVectorStyleLayer` when
- evaluating a predicate or configuring certain layout or paint attributes. To
- preserve the attributes associated with each feature, use the
+ evaluating a predicate or configuring certain layout or paint attributes. To
+ preserve the attributes associated with each feature, use the
`-initWithIdentifier:features:options:` method instead.
To create a shape from GeoJSON source code, use the
@@ -194,8 +196,8 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
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:]`.
-
- You can get/set the shapes within a collection via this property. Actions must
+
+ You can get/set the shapes within a collection via this property. Actions must
be performed on the application's main thread.
*/
@property (nonatomic, copy, nullable) MGLShape *shape;
diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm
index 50322f300c..07033d8d45 100644
--- a/platform/darwin/src/MGLShapeSource.mm
+++ b/platform/darwin/src/MGLShapeSource.mm
@@ -7,7 +7,7 @@
#import "NSURL+MGLAdditions.h"
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
@@ -34,10 +34,10 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh
if (self = [super initWithIdentifier:identifier]) {
auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options);
auto source = std::make_unique<mbgl::style::GeoJSONSource>(identifier.UTF8String, geoJSONOptions);
-
+
_pendingSource = std::move(source);
self.rawSource = _pendingSource.get();
-
+
self.URL = url;
}
return self;
@@ -47,10 +47,10 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh
if (self = [super initWithIdentifier:identifier]) {
auto geoJSONOptions = MGLGeoJSONOptionsFromDictionary(options);
auto source = std::make_unique<mbgl::style::GeoJSONSource>(identifier.UTF8String, geoJSONOptions);
-
+
_pendingSource = std::move(source);
self.rawSource = _pendingSource.get();
-
+
self.shape = shape;
}
return self;
@@ -128,7 +128,7 @@ const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLSh
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
@@ -136,7 +136,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGL
}
geoJSONOptions.maxzoom = value.integerValue;
}
-
+
if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
@@ -144,7 +144,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGL
}
geoJSONOptions.buffer = value.integerValue;
}
-
+
if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
@@ -152,7 +152,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGL
}
geoJSONOptions.tolerance = value.doubleValue;
}
-
+
if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
@@ -160,7 +160,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGL
}
geoJSONOptions.clusterRadius = value.integerValue;
}
-
+
if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
@@ -168,7 +168,7 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGL
}
geoJSONOptions.clusterMaxZoom = value.integerValue;
}
-
+
if (NSNumber *value = options[MGLShapeSourceOptionClustered]) {
if (![value isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
@@ -176,6 +176,6 @@ mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGL
}
geoJSONOptions.cluster = value.boolValue;
}
-
+
return geoJSONOptions;
}
diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h
index 584a5a4b30..c14f4fbb59 100644
--- a/platform/darwin/src/MGLShapeSource_Private.h
+++ b/platform/darwin/src/MGLShapeSource_Private.h
@@ -1,5 +1,5 @@
+#import "MGLFoundation.h"
#import "MGLShapeSource.h"
-#import "MGLShapeSource_Private.h"
NS_ASSUME_NONNULL_BEGIN
@@ -16,6 +16,7 @@ namespace mbgl {
@end
+MGL_EXPORT
mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLSource.h b/platform/darwin/src/MGLSource.h
index 03bb5fcba2..8bf48907cc 100644
--- a/platform/darwin/src/MGLSource.h
+++ b/platform/darwin/src/MGLSource.h
@@ -1,5 +1,7 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
@@ -8,16 +10,17 @@ NS_ASSUME_NONNULL_BEGIN
`MGLStyle` object along with an `MGLForegroundStyleLayer` object. The
foreground style layer defines the appearance of any content supplied by the
source.
-
+
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`, `MGLVectorSource` and `MGLRasterSource`.
*/
+MGL_EXPORT
@interface MGLSource : NSObject
#pragma mark Initializing a Source
@@ -26,10 +29,10 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a source initialized with an identifier.
-
+
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.
@return An initialized source.
diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h
index 6e1d2e379c..acb325e2f3 100644
--- a/platform/darwin/src/MGLSource_Private.h
+++ b/platform/darwin/src/MGLSource_Private.h
@@ -18,29 +18,29 @@ namespace mbgl {
- (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource;
/**
- A raw pointer to the mbgl object, which is always initialized, either to the
+ A raw pointer to the mbgl object, which is always initialized, either to the
value returned by `mbgl::Map getSource`, or for independently created objects,
to the pointer value held in `pendingSource`. In the latter case, this raw
- pointer value stays even after ownership of the object is transferred via
+ pointer value stays even after ownership of the object is transferred via
`mbgl::Map addSource`.
*/
@property (nonatomic) mbgl::style::Source *rawSource;
/**
Adds the mbgl source that this object represents to the mbgl map.
-
+
Once a mbgl source is added, ownership of the object is transferred to the
`mbgl::Map` and this object no longer has an active unique_ptr reference to the
- `mbgl::Source`. If this object's mbgl source is in that state, the mbgl source
- can still be changed but the changes will not be visible until the `MGLSource`
- is added back to the map via `-[MGLStyle addSource:]` and styled with a
+ `mbgl::Source`. If this object's mbgl source is in that state, the mbgl source
+ can still be changed but the changes will not be visible until the `MGLSource`
+ is added back to the map via `-[MGLStyle addSource:]` and styled with a
`MGLLayer`.
*/
- (void)addToMapView:(MGLMapView *)mapView;
/**
Removes the mbgl source that this object represents from the mbgl map.
-
+
When a mbgl source is removed, ownership of the object is transferred back
to the `MGLSource` instance and the unique_ptr reference is valid again. It is
safe to add the source back to the style after it is removed.
diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h
index 8c30b069b8..689faf78cf 100644
--- a/platform/darwin/src/MGLStyle.h
+++ b/platform/darwin/src/MGLStyle.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLStyleLayer.h"
#import "MGLTypes.h"
@@ -27,24 +28,25 @@ NS_ASSUME_NONNULL_BEGIN
the constant itself. Such details may change significantly from version to
version.
*/
-static const NSInteger MGLStyleDefaultVersion = 9;
+static MGL_EXPORT const NSInteger MGLStyleDefaultVersion = 9;
/**
The proxy object for the current map style.
-
+
MGLStyle provides a set of convenience methods for changing Mapbox
default styles using `-[MGLMapView styleURL]`.
<a href="https://www.mapbox.com/maps/">Learn more about Mapbox default styles</a>.
-
- It is also possible to directly manipulate the current map style
+
+ 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
+ style via any of the `MGLStyle` instance methods below. You can use the
`-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` or
`-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` methods as indicators
that it's safe to modify the map's style.
*/
+MGL_EXPORT
@interface MGLStyle : NSObject
#pragma mark Accessing Default Styles
@@ -197,7 +199,7 @@ static const NSInteger MGLStyleDefaultVersion = 9;
@note Source identifiers 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”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids source identifer name changes that will occur in the default
style’s sources over time.
@@ -209,15 +211,15 @@ 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
`MGLRedundantSourceException`. Reusing the same source identifier, even with
- different source instances, will result in a
- `MGLRedundantSourceIdentifierException`.
-
- @note Sources should be added in
+ different source instances, will result in a
+ `MGLRedundantSourceIdentifierException`.
+
+ @note Sources should be added in
`-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` or
- `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` to ensure that the map
+ `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` to ensure that the map
has loaded the style and is ready to accept a new source.
@param source The source to add to the current style.
@@ -226,11 +228,11 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Removes a source from the current style.
-
+
@note Source identifiers 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”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids source identifer name changes that will occur in the default
style’s sources over time.
@@ -249,15 +251,15 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Returns a style layer with the given identifier in the current style.
-
+
@note Layer identifiers 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”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids layer identifer name changes that will occur in the default
style’s layers over time.
-
+
@return An instance of a concrete subclass of `MGLStyleLayer` associated with
the given identifier, or `nil` if the current style contains no such style
layer.
@@ -266,14 +268,14 @@ 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.
-
- @note Layers should be added in
+ different layer instances, will also result in an exception.
+
+ @note Layers should be added in
`-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` or
- `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` to ensure that the map
+ `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` to ensure that the map
has loaded the style and is ready to accept a new layer.
@param layer The layer object to add to the map view. This object must be an
@@ -283,14 +285,14 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Inserts a new layer into the style at the given index.
-
+
@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.
-
+ different layer instances, will also result in an exception.
+
@note Layers should be added in
`-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` or
- `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` to ensure that the map
+ `-[MGLMapViewDelegate mapViewDidFinishLoadingMap:]` to ensure that the map
has loaded the style and is ready to accept a new layer.
@param layer The layer to insert.
@@ -302,15 +304,15 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Inserts a new layer below another layer.
-
+
@note Layer identifiers 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”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids layer identifer name changes that will occur in the default
style’s layers over time.
-
+
Inserting 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.
@@ -322,15 +324,15 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Inserts a new layer above another layer.
-
+
@note Layer identifiers 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”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids layer identifer name changes that will occur in the default
style’s layers over time.
-
+
Inserting 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.
@@ -342,11 +344,11 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Removes a layer from the map view.
-
+
@note Layer identifiers 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”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids layer identifer name changes that will occur in the default
style’s layers over time.
@@ -381,11 +383,11 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Deactivates the style class with the given identifier.
-
+
@note Style class names are not guaranteed to exist across styles or different
versions of the same style. Applications that use this API must first set the
style URL to an explicitly versioned style using a convenience method like
- `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`'s “Style URL”
+ `+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
approach also avoids style class name changes that will occur in the default
style over time.
@@ -398,15 +400,15 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
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
+ `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.
@@ -415,11 +417,11 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
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 `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.
*/
@@ -427,19 +429,35 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Removes a name and its associated image from 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
+ `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 of the image to remove.
*/
- (void)removeImageForName:(NSString *)name;
+#pragma mark Managing a Style’s Transition Options
+
+/**
+ The duration in seconds to animate any changes to the style URL or to layout and paint attributes.
+
+ By default, this property is set to zero seconds, so any changes take effect without animation.
+ */
+@property (nonatomic) NSTimeInterval transitionDuration;
+
+/**
+ The delay in seconds to before applying any changes to the style URL or to layout and paint attributes.
+
+ By default, this property is set to zero seconds, so any changes begin to animate immediately.
+ */
+@property (nonatomic) NSTimeInterval transitionDelay;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index fcfa762972..bcb8100800 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -24,6 +24,7 @@
#import "MGLAttributionInfo_Private.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -36,7 +37,6 @@
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/sources/raster_source.hpp>
-#include <mbgl/mbgl.hpp>
#if TARGET_OS_IPHONE
#import "UIImage+MGLAdditions.h"
@@ -71,7 +71,11 @@ static_assert(mbgl::util::default_styles::currentVersion == MGLStyleDefaultVersi
} \
\
+ (NSURL *)name##StyleURL##WithVersion:(NSInteger)version { \
- return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \
+ if (mbgl::util::default_styles::currentVersion == version) { \
+ return [NSURL URLWithString:@(mbgl::util::default_styles::name.url)]; \
+ } else { \
+ return [NSURL URLWithString:[@"mapbox://styles/mapbox/" #fileName "-v" stringByAppendingFormat:@"%li", (long)version]]; \
+ } \
}
MGL_DEFINE_STYLE(streets, streets)
@@ -213,7 +217,7 @@ static NSURL *MGLStyleURL_emerald;
if (![source isKindOfClass:[MGLTileSource class]]) {
continue;
}
-
+
NSArray *tileSetInfos = [source attributionInfosWithFontSize:fontSize linkColor:linkColor];
[infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
}
@@ -317,7 +321,7 @@ static NSURL *MGLStyleURL_emerald;
- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer
{
NSParameterAssert(mbglLayer);
-
+
NSString *identifier = @(mbglLayer->getID().c_str());
MGLStyleLayer *styleLayer;
if (auto fillLayer = mbglLayer->as<mbgl::style::FillLayer>()) {
@@ -434,7 +438,7 @@ static NSURL *MGLStyleURL_emerald;
@"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].",
sibling];
}
-
+
auto layers = self.mapView.mbglMap->getLayers();
std::string siblingIdentifier = sibling.identifier.UTF8String;
NSUInteger index = 0;
@@ -444,7 +448,7 @@ static NSURL *MGLStyleURL_emerald;
}
index++;
}
-
+
[self willChangeValueForKey:@"layers"];
if (index + 1 > layers.size()) {
[NSException raise:NSInvalidArgumentException
@@ -498,7 +502,7 @@ static NSURL *MGLStyleURL_emerald;
newAppliedClasses.push_back([appliedClass UTF8String]);
}
- mbgl::style::TransitionOptions transition { { MGLDurationInSeconds(transitionDuration) } };
+ mbgl::style::TransitionOptions transition { { MGLDurationInSecondsFromTimeInterval(transitionDuration) } };
self.mapView.mbglMap->setTransitionOptions(transition);
self.mapView.mbglMap->setClasses(newAppliedClasses);
}
@@ -566,6 +570,34 @@ static NSURL *MGLStyleURL_emerald;
return spriteImage ? [[MGLImage alloc] initWithMGLSpriteImage:spriteImage] : nil;
}
+#pragma mark Style transitions
+
+- (void)setTransitionDuration:(NSTimeInterval)duration
+{
+ auto transitionOptions = self.mapView.mbglMap->getTransitionOptions();
+ transitionOptions.duration = MGLDurationInSecondsFromTimeInterval(duration);
+ self.mapView.mbglMap->setTransitionOptions(transitionOptions);
+}
+
+- (NSTimeInterval)transitionDuration
+{
+ const mbgl::style::TransitionOptions transitionOptions = self.mapView.mbglMap->getTransitionOptions();
+ return MGLTimeIntervalFromDurationInSeconds(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+}
+
+- (void)setTransitionDelay:(NSTimeInterval)delay
+{
+ auto transitionOptions = self.mapView.mbglMap->getTransitionOptions();
+ transitionOptions.delay = MGLDurationInSecondsFromTimeInterval(delay);
+ self.mapView.mbglMap->setTransitionOptions(transitionOptions);
+}
+
+- (NSTimeInterval)transitionDelay
+{
+ const mbgl::style::TransitionOptions transitionOptions = self.mapView.mbglMap->getTransitionOptions();
+ return MGLTimeIntervalFromDurationInSeconds(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+}
+
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; name = %@, URL = %@>",
diff --git a/platform/darwin/src/MGLStyleLayer.h b/platform/darwin/src/MGLStyleLayer.h
index a91ac11c2d..55f1a56490 100644
--- a/platform/darwin/src/MGLStyleLayer.h
+++ b/platform/darwin/src/MGLStyleLayer.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLTypes.h"
NS_ASSUME_NONNULL_BEGIN
@@ -8,16 +9,17 @@ NS_ASSUME_NONNULL_BEGIN
`MGLStyleLayer` is an abstract base class for style layers. A style layer
manages the layout and appearance of content at a specific z-index in a style.
An `MGLStyle` object consists of one or more `MGLStyleLayer` objects.
-
+
Each style layer defined by the style JSON file is represented at runtime by an
`MGLStyleLayer` object, which you can use to refine the map’s appearance. You
can also add and remove style layers dynamically.
-
+
Do not create instances of this class directly, and do not create your own
subclasses of this class. Instead, create instances of
`MGLBackgroundStyleLayer` and the concrete subclasses of
`MGLForegroundStyleLayer`.
*/
+MGL_EXPORT
@interface MGLStyleLayer : NSObject
#pragma mark Initializing a Style Layer
@@ -26,16 +28,16 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a style layer object initialized with the given identifier.
-
+
The default implementation of this initializer in MGLStyleLayer creates an
invalid style layer. Call this initializer on `MGLBackgroundStyleLayer` or one of
the concrete subclasses of `MGLForegroundStyleLayer` to create a valid style
layer.
-
+
After initializing and configuring the style layer, add it to a map view’s
style using the `-[MGLStyle addLayer:]` or
- `-[MGLStyle insertLayer:belowLayer:]` method.
-
+ `-[MGLStyle insertLayer:belowLayer:]` method.
+
@param identifier A string that uniquely identifies the layer in the style to
which it is added.
@return An initialized style layer.
diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs
index a10512dbcb..f0a4ba64a3 100644
--- a/platform/darwin/src/MGLStyleLayer.h.ejs
+++ b/platform/darwin/src/MGLStyleLayer.h.ejs
@@ -5,9 +5,10 @@
const paintProperties = locals.paintProperties;
const enumProperties = locals.enumProperties;
-%>
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGL<%-
(type === 'background' ? '' :
@@ -21,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
<% if (property.type == "enum") { -%>
/**
<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %>
-
+
Values of this type are used in the `MGL<%- camelize(type) %>StyleLayer.<%- camelizeWithLeadingLowercase(property.name) %>`
property.
*/
@@ -40,7 +41,7 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) {
<% if (property.type == "enum") { -%>
/**
<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %>
-
+
Values of this type are used in the `MGL<%- camelize(type) %>StyleLayer.<%- camelizeWithLeadingLowercase(property.name) %>`
property.
*/
@@ -62,19 +63,20 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) {
<% } else { -%>
/**
<%- doc.wrap(80, 1) %>
-
+
You can access an existing <%- type %> style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new <%- type %> style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
### Example
-
+
```swift
```
*/
<% } -%>
+MGL_EXPORT
@interface MGL<%- camelize(type) %>StyleLayer : MGL<%-
(type === 'background' ? '' :
(type === 'raster' ? 'Foreground' :
diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm
index 97f8f86b26..47f41e0388 100644
--- a/platform/darwin/src/MGLStyleLayer.mm
+++ b/platform/darwin/src/MGLStyleLayer.mm
@@ -61,7 +61,7 @@
- (float)minimumZoomLevel
{
MGLAssertStyleLayerIsValid();
-
+
return self.rawLayer->getMinZoom();
}
diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs
index ec8f8599b3..4cdec72aa4 100644
--- a/platform/darwin/src/MGLStyleLayer.mm.ejs
+++ b/platform/darwin/src/MGLStyleLayer.mm.ejs
@@ -4,8 +4,8 @@
const paintProperties = locals.paintProperties;
const enumProperties = locals.enumProperties;
-%>
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -14,8 +14,10 @@
#import "MGLStyleValue_Private.h"
#import "MGL<%- camelize(type) %>StyleLayer.h"
-#include <mbgl/style/layers/<%- type %>_layer.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
<% if (enumProperties) { -%>
+
namespace mbgl {
<% if (layoutProperties.length) { -%>
@@ -93,7 +95,7 @@ namespace mbgl {
- (NSString *)sourceIdentifier
{
MGLAssertStyleLayerIsValid();
-
+
return @(self.rawLayer->getSourceID().c_str());
}
@@ -174,24 +176,42 @@ namespace mbgl {
- (void)set<%- camelize(property.name) %>:(MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> {
MGLAssertStyleLayerIsValid();
-<% if (property.type == "enum") { -%>
- auto mbglValue = MGLStyleValueTransformer<<%- mbglType(property) %>, NSValue *, <%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumPropertyValue(<%- objCName(property) %>);
- self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% if (property["property-function"]) { -%>
+ auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toDataDrivenPropertyValue(<%- objCName(property) %>);
<% } else { -%>
+<% if (property.type == "enum") { -%>
+ auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toEnumPropertyValue(<%- objCName(property) %>);
+<% } else if (property.function == "piecewise-constant") { -%>
auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue(<%- objCName(property) %>);
- self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% } else { -%>
+ auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toInterpolatablePropertyValue(<%- objCName(property) %>);
<% } -%>
+<% } -%>
+ self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
}
- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCGetter(property) %> {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
+ auto propertyValue = self.rawLayer->get<%- camelize(originalPropertyName(property)) %>();
+<% if (property["property-function"]) { -%>
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toDataDrivenStyleValue(self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>());
+ }
+ return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toDataDrivenStyleValue(propertyValue);
+<% } else { -%>
<% if (property.type == "enum") { -%>
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<<%- mbglType(property) %>, NSValue *, <%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumStyleValue(self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>());
+ }
return MGLStyleValueTransformer<<%- mbglType(property) %>, NSValue *, <%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumStyleValue(propertyValue);
<% } else { -%>
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>());
+ }
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(propertyValue);
<% } -%>
+<% } -%>
}
<% if (property.original) { -%>
@@ -212,24 +232,42 @@ namespace mbgl {
- (void)set<%- camelize(property.name) %>:(MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> {
MGLAssertStyleLayerIsValid();
-<% if (property.type == "enum") { -%>
- auto mbglValue = MGLStyleValueTransformer<<%- mbglType(property) %>, NSValue *, <%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumPropertyValue(<%- objCName(property) %>);
- self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% if (property["property-function"]) { -%>
+ auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toDataDrivenPropertyValue(<%- objCName(property) %>);
<% } else { -%>
+<% if (property.type == "enum") { -%>
+ auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toEnumPropertyValue(<%- objCName(property) %>);
+<% } else if (property.function == "piecewise-constant") { -%>
auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue(<%- objCName(property) %>);
- self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% } else { -%>
+ auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toInterpolatablePropertyValue(<%- objCName(property) %>);
+<% } -%>
<% } -%>
+ self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
}
- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCGetter(property) %> {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
+ auto propertyValue = self.rawLayer->get<%- camelize(originalPropertyName(property)) %>();
+<% if (property["property-function"]) { -%>
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toDataDrivenStyleValue(self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>());
+ }
+ return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toDataDrivenStyleValue(propertyValue);
+<% } else { -%>
<% if (property.type == "enum") { -%>
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<<%- mbglType(property) %>, NSValue *, <%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumStyleValue(self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>());
+ }
return MGLStyleValueTransformer<<%- mbglType(property) %>, NSValue *, <%- mbglType(property) %>, MGL<%- camelize(property.name) %>>().toEnumStyleValue(propertyValue);
<% } else { -%>
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>());
+ }
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(propertyValue);
<% } -%>
+<% } -%>
}
<% if (property.original) { -%>
diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h
index c5e3e76549..b5d709a7af 100644
--- a/platform/darwin/src/MGLStyleLayer_Private.h
+++ b/platform/darwin/src/MGLStyleLayer_Private.h
@@ -3,7 +3,6 @@
#import "MGLStyleLayer.h"
#import "MGLStyleValue_Private.h"
-#include <mbgl/mbgl.hpp>
#include <mbgl/style/layer.hpp>
NS_ASSUME_NONNULL_BEGIN
@@ -54,9 +53,9 @@ NS_ASSUME_NONNULL_BEGIN
/**
Removes the mbgl style layer that this object represents from the mbgl map.
-
+
When a mbgl style layer is removed, ownership of the object is transferred back
- to the `MGLStyleLayer` instance and the unique_ptr reference is valid again. It
+ to the `MGLStyleLayer` instance and the unique_ptr reference is valid again. It
is safe to add the layer back to the style after it is removed.
*/
- (void)removeFromMapView:(MGLMapView *)mapView;
diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h
index eec7ed9781..2ce2eae89a 100644
--- a/platform/darwin/src/MGLStyleValue.h
+++ b/platform/darwin/src/MGLStyleValue.h
@@ -1,19 +1,92 @@
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
+#import "MGLFoundation.h"
+#import "MGLTypes.h"
+
NS_ASSUME_NONNULL_BEGIN
/**
+ Options for `MGLStyleFunction` objects.
+ */
+typedef NSString *MGLStyleFunctionOption NS_STRING_ENUM;
+
+/**
+ An `NSNumber` object containing an integer that determines the style function's
+ exponential interpolation base.
+
+ The exponential interpolation base controls the rate at which the function’s
+ output values increase. A value of 1 causes the function to increase linearly
+ by zoom level. A higher exponential interpolation base causes the function’s
+ output values to vary exponentially, increasing more rapidly towards the high
+ end of the function’s range. The default value of this property is 1, for a
+ linear curve.
+
+ This attribute corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#function-base"><code>base</code></a>
+ function property in the Mapbox Style Specification.
+
+ This option only applies to functions that use an
+ `MGLInterpolationModeExponential` interpolation mode that are assigned to
+ interpolatable style layer properties.
+ */
+extern MGL_EXPORT const MGLStyleFunctionOption MGLStyleFunctionOptionInterpolationBase;
+
+/**
+ An `MGLStyleConstantValue` object that specifies a default value that a style
+ function can use when it can't otherwise determine a value.
+
+ A default value can be used to set the value of a style layer property that
+ is not otherwise set by a function. For example, a source function with a
+ `MGLInterpolationModeCategorical` interpolation mode with stops that specify
+ color values to use based on a feature's attributes would set any feature
+ that does not have attributes that match the stop key values to this
+ default value.
+
+ This option only applies to `MGLSourceStyleFunction` and
+ `MGLCompositeStyleFunction` functions.
+ */
+extern MGL_EXPORT const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue;
+
+/**
+ The modes used to interpolate property values between map zoom level changes
+ or over a range of feature attribute values.
+ */
+typedef NS_ENUM(NSUInteger, MGLInterpolationMode) {
+ /**
+ Values between two stops are interpolated exponentially or linearly if the
+ `MGLStyleFunctionOptionInterpolationBase` is 1.
+ */
+ MGLInterpolationModeExponential = 0,
+ /**
+ Values between two stops are not interpolated. Instead, properties are set
+ to the value of the stop just less than the function input.
+ */
+ MGLInterpolationModeInterval,
+ /**
+ Values between two stops are not interpolated. Instead, properties are set
+ to the value of the stop equal to the function input's key value.
+ */
+ MGLInterpolationModeCategorical,
+ /**
+ Values between two stops are not interpolated. Instead, values are set
+ to their input value.
+ */
+ MGLInterpolationModeIdentity
+};
+
+/**
An `MGLStyleValue` object is a generic container for a style attribute value.
The layout and paint attribute properties of `MGLStyleLayer` can be set to
`MGLStyleValue` objects.
-
+
The `MGLStyleValue` class itself represents a class cluster. Under the hood, a
particular `MGLStyleValue` object may be either an `MGLStyleConstantValue` to
- represent a constant value or an `MGLStyleFunction` to represent a value
- function. Do not initialize an `MGLStyleValue` object directly; instead, use
- one of the class factory methods to create an `MGLStyleValue` object.
-
+ represent a constant value or one of the concrete subclasses of
+ `MGLStyleFunction` to represent a value function. Do not initialize an
+ `MGLStyleValue` object directly; instead, use one of the class factory methods
+ to create an `MGLStyleValue` object.
+
The `MGLStyleValue` class takes a generic parameter `T` that indicates the
Foundation class being wrapped by this class. Common values for `T` include:
@@ -25,37 +98,85 @@ NS_ASSUME_NONNULL_BEGIN
<li><code>NSArray</code></li>
</ul>
*/
+MGL_EXPORT
@interface MGLStyleValue<T> : NSObject
#pragma mark Creating a Style Value
/**
Creates and returns an `MGLStyleConstantValue` object containing a raw value.
-
+
@param rawValue The constant value contained by the object.
@return An `MGLStyleConstantValue` object containing `rawValue`, which is
treated as a constant value.
*/
+ (instancetype)valueWithRawValue:(T)rawValue;
+#pragma mark Function values
+
/**
- Creates and returns an `MGLStyleFunction` object representing a linear zoom
- level function with any number of stops.
-
+ Creates and returns an `MGLCameraStyleFunction` object representing a linear camera
+ function with one or more stops.
+
@param stops A dictionary associating zoom levels with style values.
- @return An `MGLStyleFunction` object with the given stops.
+ @return An `MGLCameraStyleFunction` object with the given stops.
*/
-+ (instancetype)valueWithStops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
++ (instancetype)valueWithStops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
/**
- Creates and returns an `MGLStyleFunction` object representing a zoom level
- function with an exponential interpolation base and any number of stops.
-
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with an exponential interpolation base and one or more stops.
+
@param interpolationBase The exponential base of the interpolation curve.
@param stops A dictionary associating zoom levels with style values.
- @return An `MGLStyleFunction` object with the given interpolation base and stops.
+ @return An `MGLCameraStyleFunction` object with the given interpolation base and stops.
+ */
++ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
+
+/**
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera function
+ with one or more stops.
+
+ @param interpolationMode The mode used to interpolate property values between
+ map zoom level changes.
+ @param cameraStops A dictionary associating zoom levels with style values.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCameraStyleFunction` object with the given interpolation mode,
+ camera stops, and options.
+ */
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode cameraStops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)cameraStops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+
+/**
+ Creates and returns an `MGLSourceStyleFunction` object representing a source function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLSourceStyleFunction` object with the given interpolation mode,
+ source stops, attribute name, and options.
+ */
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode sourceStops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)sourceStops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+
+/**
+ Creates and returns an `MGLCompositeStyleFunction` object representing a composite
+ function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values for each outer zoom level.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCompositeStyleFunction` object with the given interpolation mode,
+ composite stops, attribute name, and options.
*/
-+ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode compositeStops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)compositeStops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
@end
@@ -64,17 +185,18 @@ NS_ASSUME_NONNULL_BEGIN
value that remains constant as the zoom level changes. The layout and paint
attribute properties of `MGLStyleLayer` objects can be set to
`MGLStyleConstantValue` objects.
-
+
The `MGLStyleConstantValue` class takes a generic parameter `T` that indicates
the Foundation class being wrapped by this class.
*/
+MGL_EXPORT
@interface MGLStyleConstantValue<T> : MGLStyleValue<T>
#pragma mark Creating a Style Constant Value
/**
Creates and returns an `MGLStyleConstantValue` object containing a raw value.
-
+
@param rawValue The constant value contained by the object.
@return An `MGLStyleConstantValue` object containing `rawValue`, which is
treated as a constant value.
@@ -87,7 +209,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns an `MGLStyleConstantValue` object containing a raw value.
-
+
@param rawValue The value contained by the receiver.
@return An `MGLStyleConstantValue` object containing `rawValue`.
*/
@@ -103,65 +225,127 @@ NS_ASSUME_NONNULL_BEGIN
@end
/**
- An `MGLStyleFunction` is a value function defining a style value that changes
- as the zoom level changes. The layout and paint attribute properties of an
- `MGLStyleLayer` object can be set to `MGLStyleFunction` objects. Use a zoom
- level function to create the illusion of depth and control data density.
+ An `MGLStyleFunction` is a is an abstract superclass for functions that are
+ defined by an `MGLCameraStyleFunction`, `MGLSourceStyleFunction`, or
+ `MGLCompositeStyleFunction` object.
+ Do not create instances of this class directly, and do not create your own
+ subclasses of this class. Instead, use one of the class factory methods in
+ `MGLStyleValue` to create instances of the following concrete subclasses:
+ `MGLCameraStyleFunction`, `MGLSourceStyleFunction`, and
+ `MGLCompositeStyleFunction`.
+
The `MGLStyleFunction` class takes a generic parameter `T` that indicates the
Foundation class being wrapped by this class.
*/
+MGL_EXPORT
@interface MGLStyleFunction<T> : MGLStyleValue<T>
#pragma mark Creating a Style Function
/**
- Creates and returns an `MGLStyleFunction` object representing a linear zoom
- level function with any number of stops.
-
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with a linear interpolation curve.
+
+ @note Do not create function instances using this method unless it is required
+ for backwards compatiblity with your application code.
+
@param stops A dictionary associating zoom levels with style values.
- @return An `MGLStyleFunction` object with the given stops.
+ @return An `MGLCameraStyleFunction` object with the given stops.
*/
-+ (instancetype)functionWithStops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
++ (instancetype)functionWithStops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
/**
- Creates and returns an `MGLStyleFunction` object representing a zoom level
- function with an exponential interpolation base and any number of stops.
-
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with an interpolation curve controlled by the provided interpolation
+ base.
+
+ @note Do not create function instances using this method unless it is required
+ for backwards compatiblity with your application code.
+
@param interpolationBase The exponential base of the interpolation curve.
@param stops A dictionary associating zoom levels with style values.
- @return An `MGLStyleFunction` object with the given interpolation base and stops.
+ @return An `MGLCameraStyleFunction` object with the given interpolation base and stops.
*/
-+ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops;
++ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
#pragma mark Initializing a Style Function
/**
- Returns an `MGLStyleFunction` object representing a zoom level function with an
- exponential interpolation base and any number of stops.
+ Returns an `MGLStyleFunction` object representing a camera function. If the
+ function is set as a style layer property value, it will be interpreted
+ as a camera function with an interpolation curve controlled by the provided
+ interpolation base.
+ @note Do not create instances of `MGLStyleFunction` unless it is required for
+ backwards compatiblity with your application code. You should create and use
+ instances of `MGLCameraStyleFunction` to specify how properties will
+ be visualized at different zoom levels.
+
@param interpolationBase The exponential base of the interpolation curve.
@param stops A dictionary associating zoom levels with style values.
@return An `MGLStyleFunction` object with the given interpolation base and stops.
*/
-- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
#pragma mark Accessing the Parameters of a Function
/**
+ The modes used to interpolate property values between map zoom level changes or
+ over a range of feature attribute values.
+ */
+@property (nonatomic) MGLInterpolationMode interpolationMode;
+
+/**
+ A dictionary associating zoom levels with style values.
+ */
+@property (nonatomic, copy, nullable) NSDictionary *stops;
+
+/**
The exponential interpolation base of the function’s interpolation curve.
- The exponential interpolation base controls the rate at which the function’s output values
- increase. A value of 1 causes the function to increase linearly by zoom level.
- A higher exponential interpolation base causes the function’s output values to vary
- exponentially, increasing more rapidly towards the high end of the function’s
- range. The default value of this property is 1, for a linear curve.
+ @note This property specifies the exponential base of the interpolation curve
+ of `MGLCameraStyleFunction` and `MGLSourceStyleFunction` functions that use
+ a `MGLInterpolationModeExponential` `interpolationMode`. Otherwise, it is
+ ignored.
*/
@property (nonatomic) CGFloat interpolationBase;
+@end
+
+/**
+ An `MGLCameraStyleFunction` is a value function defining a style value that changes
+ as the zoom level changes. The layout and paint attribute properties of an
+ `MGLStyleLayer` object can be set to `MGLCameraStyleFunction` objects. Use a camera
+ function to create the illusion of depth and control data density.
+
+ The `MGLCameraStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
+MGL_EXPORT
+@interface MGLCameraStyleFunction<T> : MGLStyleFunction<T>
+
+#pragma mark Creating a Camera Function
+
+/**
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with one or more stops.
+
+ @param interpolationMode The mode used to interpolate property values between
+ map zoom level changes.
+ @param stops A dictionary associating zoom levels with style values.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCameraStyleFunction` object with the given interpolation mode,
+ camera stops, and options.
+ */
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+
+#pragma mark Accessing the Parameters of a Camera Function
+
/**
A dictionary associating zoom levels with style values.
-
+
Each of the function’s stops is represented by one key-value pair in the
dictionary. Each key in the dictionary is an `NSNumber` object containing a
floating-point zoom level. Each value in the dictionary is an `MGLStyleValue`
@@ -169,7 +353,128 @@ NS_ASSUME_NONNULL_BEGIN
associated zoom level. An `MGLStyleFunction` object may not be used recursively
as a stop value.
*/
-@property (nonatomic, copy) NSDictionary<NSNumber *, MGLStyleValue<T> *> *stops;
+@property (nonatomic, copy) NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *stops;
+
+@end
+
+/**
+ An `MGLSourceStyleFunction` is a value function defining a style value that
+ changes with its properties. The layout and paint attribute properties of an
+ `MGLStyleLayer` object can be set to `MGLSourceStyleFunction` objects.
+ Use source functions to visually differentate types of features within the same
+ layer or create data visualizations.
+
+ The `MGLSourceStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
+MGL_EXPORT
+@interface MGLSourceStyleFunction<T> : MGLStyleFunction<T>
+
+#pragma mark Creating a Source Function
+
+/**
+ Creates and returns an `MGLSourceStyleFunction` object representing a source
+ function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLSourceStyleFunction` object with the given interpolation mode,
+ source stops, attribute name, and options.
+*/
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+
+#pragma mark Accessing the Parameters of a Source Function
+
+/**
+ A string that specifies the feature attribute key whose value be used as the function
+ input.
+*/
+@property (nonatomic, copy) NSString *attributeName;
+
+/**
+ A dictionary associating attribute values with style values.
+
+ Each of the function’s stops is represented by one key-value pair in the
+ dictionary. Each key in the dictionary is an object representing a feature
+ attribute key or interpolation stop. Each value in the dictionary is an
+ `MGLStyleValue` object containing the value to use when the function is given
+ the associated attribute key. An `MGLStyleFunction` object may not be used
+ recursively as a stop value.
+ */
+@property (nonatomic, copy, nullable) NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *stops;
+
+/**
+ An `MGLStyleValue` object containing the default value to use when there is
+ no input to provide to the function.
+ */
+@property (nonatomic, nullable) MGLStyleValue<T> *defaultValue;
+
+@end
+
+/**
+ An `MGLCompositeStyleFunction` is a value function defining a style value that
+ changes with the feature attributes at each map zoom level. The layout and paint
+ attribute properties of an `MGLStyleLayer` object can be set to
+ `MGLCompositeStyleFunction` objects. Use composite functions to allow the
+ appearance of a map feature to change with both its attributes and the map zoom
+ level.
+
+ The `MGLCompositeStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
+MGL_EXPORT
+@interface MGLCompositeStyleFunction<T> : MGLStyleFunction<T>
+
+#pragma mark Creating a Composite Function
+
+/**
+ Creates and returns an `MGLCompositeStyleFunction` object representing a composite
+ function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values for each outer zoom level.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCompositeStyleFunction` object with the given interpolation mode,
+ composite stops, attribute name, and options.
+ */
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+
+#pragma mark Accessing the Parameters of a Composite Function
+
+/**
+ A string that specifies the feature attribute key whose value be used as the function
+ input.
+ */
+@property (nonatomic, copy) NSString *attributeName;
+
+/**
+ A dictionary associating attribute values with style values.
+
+ Each of the function’s stops is represented by one key-value pair in the
+ dictionary. Each key in the dictionary is an `NSNumber` object containing a
+ floating-point zoom level. Each value in the dictionary is an inner nested
+ dictionary. Each key in the nested dictionary is an object representing a feature
+ attribute key or interpolation stop. Each value in the nested dictionary is an
+ `MGLStyleValue` object containing the value to use when the function is given
+ the associated attribute key. An `MGLStyleFunction` object may not be used
+ recursively as a value inside the nested dictionary.
+ */
+@property (nonatomic, copy) NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *stops;
+
+/**
+ An `MGLStyleValue` object containing the default value to use when there is
+ no input to provide to the function.
+ */
+@property (nonatomic, nullable) MGLStyleValue<T> *defaultValue;
@end
diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm
index 9e77114378..020dc27d6a 100644
--- a/platform/darwin/src/MGLStyleValue.mm
+++ b/platform/darwin/src/MGLStyleValue.mm
@@ -1,5 +1,8 @@
#import "MGLStyleValue_Private.h"
+const MGLStyleFunctionOption MGLStyleFunctionOptionInterpolationBase = @"MGLStyleFunctionOptionInterpolationBase";
+const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunctionOptionDefaultValue";
+
@implementation MGLStyleValue
+ (instancetype)valueWithRawValue:(id)rawValue {
@@ -7,11 +10,23 @@
}
+ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
- return [MGLStyleFunction functionWithInterpolationBase:interpolationBase stops:stops];
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
}
+ (instancetype)valueWithStops:(NSDictionary *)stops {
- return [MGLStyleFunction functionWithStops:stops];
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:nil];
+}
+
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode cameraStops:(NSDictionary *)cameraStops options:(NSDictionary *)options {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:interpolationMode stops:cameraStops options:options];
+}
+
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode sourceStops:(NSDictionary *)sourceStops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ return [MGLSourceStyleFunction functionWithInterpolationMode:interpolationMode stops:sourceStops attributeName:attributeName options:options];
+}
+
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode compositeStops:(NSDictionary *)compositeStops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ return [MGLCompositeStyleFunction functionWithInterpolationMode:interpolationMode stops:compositeStops attributeName:attributeName options:options];
}
@end
@@ -49,44 +64,245 @@
@implementation MGLStyleFunction
-+ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
- return [[self alloc] initWithInterpolationBase:interpolationBase stops:stops];
++ (instancetype)functionWithStops:(NSDictionary *)stops {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:nil];
}
-+ (instancetype)functionWithStops:(NSDictionary *)stops {
- return [[self alloc] initWithInterpolationBase:1 stops:stops];
++ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
}
- (instancetype)init {
- return [self initWithInterpolationBase:1 stops:@{}];
+ if (self = [super init]) {
+ self.interpolationBase = 1.0;
+ self.stops = @{};
+ }
+ return self;
}
- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
if (self = [super init]) {
- if (!stops.count)
- {
- [NSException raise:NSInvalidArgumentException format:@"%@ requires at least one stop.", self];
- }
- _interpolationBase = interpolationBase;
- _stops = stops;
+ self.interpolationBase = interpolationBase;
+ self.stops = stops;
}
return self;
}
- (NSString *)description {
- return [NSString stringWithFormat:@"<%@: %p, interpolationBase = %f; stops = %@>",
+ return [NSString stringWithFormat:@"<%@: %p, \
+ stops = %@, \
+ interpolationBase = %f>",
NSStringFromClass([self class]), (void *)self,
- self.interpolationBase,
- self.stops];
+ self.stops,
+ self.interpolationBase];
}
- (BOOL)isEqual:(MGLStyleFunction *)other {
- return ([other isKindOfClass:[self class]] && other.interpolationBase == self.interpolationBase
- && [other.stops isEqualToDictionary:self.stops]);
+ return ([other isKindOfClass:[self class]]
+ && [other.stops isEqualToDictionary:self.stops]
+ && other.interpolationBase == self.interpolationBase);
+}
+
+- (NSUInteger)hash {
+ return self.stops.hash + @(self.interpolationBase).hash;
+}
+
+@end
+
+@implementation MGLCameraStyleFunction
+
+@dynamic stops;
+
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops options:(NSDictionary *)options {
+ return [[self alloc] initWithInterpolationMode:interpolationMode stops:stops options:options];
+}
+
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
+}
+
+- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops options:(NSDictionary *)options {
+ if (![stops count]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Camera functions must have at least one stop."];
+ return {};
+ }
+
+ if (self == [super init]) {
+ self.interpolationMode = interpolationMode;
+ self.stops = stops;
+
+ if ([options.allKeys containsObject:MGLStyleFunctionOptionInterpolationBase]) {
+ if ([options[MGLStyleFunctionOptionInterpolationBase] isKindOfClass:[NSNumber class]]) {
+ NSNumber *value = (NSNumber *)options[MGLStyleFunctionOptionInterpolationBase];
+ self.interpolationBase = [value floatValue];
+ } else {
+ [NSException raise:NSInvalidArgumentException format:@"Interpolation base must be an NSNumber that represents a CGFloat."];
+ }
+ }
+ }
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, \
+ interpolationMode = %lu, \
+ stops = %@, \
+ interpolationBase = %f>",
+ NSStringFromClass([self class]), (void *)self,
+ (unsigned long)self.interpolationMode,
+ self.stops,
+ self.interpolationBase];
+}
+
+- (BOOL)isEqual:(MGLCameraStyleFunction *)other {
+ return ([other isKindOfClass:[self class]]
+ && other.interpolationMode == self.interpolationMode
+ && [other.stops isEqualToDictionary:self.stops]
+ && other.interpolationBase == self.interpolationBase);
+}
+
+- (NSUInteger)hash {
+ return @(self.interpolationMode).hash + self.stops.hash + @(self.interpolationBase).hash;
+}
+
+@end
+
+@implementation MGLSourceStyleFunction
+
+@dynamic stops;
+
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ return [[self alloc] initWithInterpolationMode:interpolationMode stops:stops attributeName:attributeName options:options];
+}
+
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:stops attributeName:@"" options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
+}
+
+- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ if (self == [super init]) {
+ self.interpolationMode = interpolationMode;
+ self.stops = stops;
+ _attributeName = attributeName;
+
+ if ([options.allKeys containsObject:MGLStyleFunctionOptionDefaultValue]) {
+ if ([options[MGLStyleFunctionOptionDefaultValue] isKindOfClass:[MGLStyleValue class]]) {
+ MGLStyleValue *value = (MGLStyleValue *)options[MGLStyleFunctionOptionDefaultValue];
+ _defaultValue = value;
+ } else {
+ [NSException raise:NSInvalidArgumentException format:@"Default value must be an MGLStyleValue"];
+ }
+ }
+
+ if ([options.allKeys containsObject:MGLStyleFunctionOptionInterpolationBase]) {
+ if ([options[MGLStyleFunctionOptionInterpolationBase] isKindOfClass:[NSNumber class]]) {
+ NSNumber *value = (NSNumber *)options[MGLStyleFunctionOptionInterpolationBase];
+ self.interpolationBase = [value floatValue];
+ } else {
+ [NSException raise:NSInvalidArgumentException format:@"Interpolation base must be an NSNumber that represents a CGFloat."];
+ }
+ }
+ }
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, \
+ interpolationMode = %lu, \
+ stops = %@, \
+ attributeName = %@, \
+ defaultValue = %@, \
+ interpolationBase = %f>",
+ NSStringFromClass([self class]),
+ (void *)self,
+ (unsigned long)self.interpolationMode,
+ self.stops,
+ self.attributeName,
+ self.defaultValue,
+ self.interpolationBase];
+}
+
+- (BOOL)isEqual:(MGLSourceStyleFunction *)other {
+ return ([other isKindOfClass:[self class]]
+ && other.interpolationMode == self.interpolationMode
+ && ((self.stops && [other.stops isEqualToDictionary:self.stops]) || (!self.stops && !other.stops))
+ && [other.attributeName isEqual:self.attributeName]
+ && ((self.defaultValue && [other.defaultValue isEqual:self.defaultValue]) || (!self.defaultValue && !other.defaultValue))
+ && other.interpolationBase == self.interpolationBase);
+}
+
+- (NSUInteger)hash {
+ return @(self.interpolationMode).hash + self.stops.hash + self.attributeName.hash + self.defaultValue.hash + @(self.interpolationBase).hash;
+}
+
+@end
+
+@implementation MGLCompositeStyleFunction
+
+@dynamic stops;
+
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ return [[self alloc] initWithInterpolationMode:interpolationMode stops:stops attributeName:attributeName options:options];
+}
+
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:stops attributeName:@"" options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
+}
+
+- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ if (self == [super init]) {
+ self.interpolationMode = interpolationMode;
+ self.stops = stops;
+ _attributeName = attributeName;
+
+ if ([options.allKeys containsObject:MGLStyleFunctionOptionDefaultValue]) {
+ if ([options[MGLStyleFunctionOptionDefaultValue] isKindOfClass:[MGLStyleValue class]]) {
+ MGLStyleValue *value = (MGLStyleValue *)options[MGLStyleFunctionOptionDefaultValue];
+ _defaultValue = value;
+ } else {
+ [NSException raise:NSInvalidArgumentException format:@"Default value must be an MGLStyleValue"];
+ }
+ }
+
+ if ([options.allKeys containsObject:MGLStyleFunctionOptionInterpolationBase]) {
+ if ([options[MGLStyleFunctionOptionInterpolationBase] isKindOfClass:[NSNumber class]]) {
+ NSNumber *value = (NSNumber *)options[MGLStyleFunctionOptionInterpolationBase];
+ self.interpolationBase = [value floatValue];
+ } else {
+ [NSException raise:NSInvalidArgumentException format:@"Interpolation base must be an NSNumber that represents a CGFloat."];
+ }
+ }
+ }
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, \
+ interpolationMode = %lu, \
+ stops = %@, \
+ attributeName = %@, \
+ defaultValue = %@, \
+ interpolationBase = %f>",
+ NSStringFromClass([self class]), (void *)self,
+ (unsigned long)self.interpolationMode,
+ self.stops,
+ self.attributeName,
+ self.defaultValue,
+ self.interpolationBase];
+}
+
+- (BOOL)isEqual:(MGLCompositeStyleFunction *)other {
+ return ([other isKindOfClass:[self class]]
+ && other.interpolationMode == self.interpolationMode
+ && [other.stops isEqualToDictionary:self.stops]
+ && [other.attributeName isEqual:self.attributeName]
+ && ((self.defaultValue && [other.defaultValue isEqual:self.defaultValue]) || (!self.defaultValue && !other.defaultValue))
+ && other.interpolationBase == self.interpolationBase);
}
- (NSUInteger)hash {
- return self.interpolationBase + self.stops.hash;
+ return @(self.interpolationMode).hash + self.stops.hash + self.attributeName.hash + @(self.interpolationBase).hash;
}
@end
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index 2c3de3fb74..3a5ce8d474 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -4,64 +4,108 @@
#import "NSValue+MGLStyleAttributeAdditions.h"
#import "MGLTypes.h"
+
+#import "MGLConversion.h"
+#include <mbgl/style/conversion/data_driven_property_value.hpp>
+#include <mbgl/style/conversion.hpp>
+
#import <mbgl/util/enum.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
+
+#include <mbgl/util/interpolate.hpp>
+
#if TARGET_OS_IPHONE
#import "UIColor+MGLAdditions.h"
#else
#import "NSColor+MGLAdditions.h"
#endif
-#include <array>
-
template <typename MBGLType, typename ObjCType, typename MBGLElement = MBGLType, typename ObjCEnum = ObjCType>
class MGLStyleValueTransformer {
public:
-
+
+ // Convert an mbgl property value into an mgl style value
MGLStyleValue<ObjCType> *toStyleValue(const mbgl::style::PropertyValue<MBGLType> &mbglValue) {
- if (mbglValue.isConstant()) {
- return toStyleConstantValue(mbglValue.asConstant());
- } else if (mbglValue.isFunction()) {
- return toStyleFunction(mbglValue.asFunction());
- } else {
- return nil;
- }
+ PropertyValueEvaluator evaluator;
+ return mbglValue.evaluate(evaluator);
}
+ // Convert an mbgl data driven property value into an mgl style value
+ MGLStyleValue<ObjCType> *toDataDrivenStyleValue(const mbgl::style::DataDrivenPropertyValue<MBGLType> &mbglValue) {
+ PropertyValueEvaluator evaluator;
+ return mbglValue.evaluate(evaluator);
+ }
+
+ // Convert an mbgl property value containing an enum into an mgl style value
template <typename MBGLEnum = MBGLType,
class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
typename MGLEnum = ObjCEnum,
class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
MGLStyleValue<ObjCType> *toEnumStyleValue(const mbgl::style::PropertyValue<MBGLEnum> &mbglValue) {
- if (mbglValue.isConstant()) {
- return toEnumStyleConstantValue<>(mbglValue.asConstant());
- } else if (mbglValue.isFunction()) {
- const auto &mbglStops = mbglValue.asFunction().getStops();
- NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.size()];
- for (const auto &mbglStop : mbglStops) {
- stops[@(mbglStop.first)] = toEnumStyleConstantValue<>(mbglStop.second);
- }
- return [MGLStyleFunction<NSValue *> functionWithInterpolationBase:mbglValue.asFunction().getBase() stops:stops];
+ EnumPropertyValueEvaluator<MBGLEnum, ObjCEnum> evaluator;
+ return mbglValue.evaluate(evaluator);
+ }
+
+ // Convert an mgl style value into a non interpolatable (camera with interval stops) mbgl property value
+ mbgl::style::PropertyValue<MBGLType> toPropertyValue(MGLStyleValue<ObjCType> *value) {
+ if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"This property can only be set to camera functions. Use +[MGLStyleValue cameraFunctionValueWithinterpolationMode:stops:options:] instead."];
+ return {};
+ }
+
+ if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
+ return toMBGLConstantValue((MGLStyleConstantValue<ObjCType> *)value);
+ } else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) {
+ MGLCameraStyleFunction<ObjCType> *cameraStyleFunction = (MGLCameraStyleFunction<ObjCType> *)value;
+ // Intentionally ignore the stop type set by the developer becuase non interpolatable property values
+ // can only have interval stops. This also allows for backwards compatiblity when the developer uses
+ // a deprecated MGLStyleValue method (that used to create an MGLStyleFunction) to create a function
+ // for properties that are piecewise-constant (i.e. enum, bool, string)
+ return toMBGLIntervalCameraFunction(cameraStyleFunction);
+ } else if ([value isMemberOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value;
+ return toMBGLIntervalCameraFunction(styleFunction);
+ } else if (value) {
+ [NSException raise:@"MGLAbstractClassException" format:
+ @"The style value %@ cannot be applied to the style. "
+ @"Make sure the style value was created as a member of a concrete subclass of MGLStyleValue.",
+ NSStringFromClass([value class])];
+ return {};
} else {
- return nil;
+ return {};
}
}
- mbgl::style::PropertyValue<MBGLType> toPropertyValue(MGLStyleValue<ObjCType> *value) {
+ // Convert an mgl style value into a non interpolatable (camera with exponential or interval stops) mbgl property value
+ mbgl::style::PropertyValue<MBGLType> toInterpolatablePropertyValue(MGLStyleValue<ObjCType> *value) {
+ if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"This property can only be set to camera functions. Use +[MGLStyleValue cameraFunctionValueWithinterpolationMode:stops:options:] instead."];
+ return {};
+ }
+
if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
- MBGLType mbglValue;
- getMBGLValue([(MGLStyleConstantValue<ObjCType> *)value rawValue], mbglValue);
- return mbglValue;
- } else if ([value isKindOfClass:[MGLStyleFunction class]]) {
- MGLStyleFunction<ObjCType> *function = (MGLStyleFunction<ObjCType> *)value;
- __block std::vector<std::pair<float, MBGLType>> mbglStops;
- [function.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
- NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
- auto mbglStopValue = toPropertyValue(stopValue);
- NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
- mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant());
- }];
- return mbgl::style::Function<MBGLType>({{mbglStops}}, function.interpolationBase);
+ return toMBGLConstantValue((MGLStyleConstantValue<ObjCType> *)value);
+ } else if ([value isMemberOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value;
+ return toMBGLExponentialCameraFunction(styleFunction);
+ } else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) {
+ MGLCameraStyleFunction<ObjCType> *cameraStyleFunction = (MGLCameraStyleFunction<ObjCType> *)value;
+ switch (cameraStyleFunction.interpolationMode) {
+ case MGLInterpolationModeExponential:
+ return toMBGLExponentialCameraFunction(cameraStyleFunction);
+ break;
+ case MGLInterpolationModeInterval:
+ return toMBGLIntervalCameraFunction(cameraStyleFunction);
+ break;
+ default:
+ [NSException raise:NSInvalidArgumentException
+ format:@"A camera function must use either exponential or interval stops."];
+ break;
+ }
+ return {};
} else if (value) {
[NSException raise:@"MGLAbstractClassException" format:
@"The style value %@ cannot be applied to the style. "
@@ -73,25 +117,51 @@ public:
}
}
+ // Convert an mgl style value into a mbgl data driven property value
+ mbgl::style::DataDrivenPropertyValue<MBGLType> toDataDrivenPropertyValue(MGLStyleValue<ObjCType> *value) {
+ if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
+ return toMBGLConstantValue((MGLStyleConstantValue<ObjCType> *)value);
+ } else if ([value isKindOfClass:[MGLStyleFunction class]]) {
+ auto rawValue = toRawStyleSpecValue((MGLStyleFunction<ObjCType> *) value);
+ auto result = mbgl::style::conversion::convert<mbgl::style::DataDrivenPropertyValue<MBGLType>>(rawValue);
+ NSCAssert(result, @(result.error().message.c_str()));
+ return *result;
+ } else {
+ return {};
+ }
+ }
+
+ // Convert an mgl style value containing an enum into a mbgl property value containing an enum
template <typename MBGLEnum = MBGLType,
class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
typename MGLEnum = ObjCEnum,
class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
mbgl::style::PropertyValue<MBGLEnum> toEnumPropertyValue(MGLStyleValue<ObjCType> *value) {
+ if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"This property can only be set to camera functions. Use +[MGLStyleValue cameraFunctionValueWithinterpolationMode:stops:options:] instead."];
+ return {};
+ }
+
if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
MBGLEnum mbglValue;
getMBGLValue([(MGLStyleConstantValue<ObjCType> *)value rawValue], mbglValue);
return mbglValue;
- } else if ([value isKindOfClass:[MGLStyleFunction class]]) {
- MGLStyleFunction<NSValue *> *function = (MGLStyleFunction<NSValue *> *)value;
- __block std::vector<std::pair<float, MBGLEnum>> mbglStops;
- [function.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<NSValue *> * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ } else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) {
+ MGLCameraStyleFunction<NSValue *> *cameraStyleFunction = (MGLCameraStyleFunction<NSValue *> *)value;
+ __block std::map<float, MBGLType> stops = {};
+ [cameraStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<NSValue *> * _Nonnull stopValue, BOOL * _Nonnull stop) {
NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
auto mbglStopValue = toEnumPropertyValue(stopValue);
NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
- mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant());
+ stops[zoomKey.floatValue] = mbglStopValue.asConstant();
}];
- return mbgl::style::Function<MBGLEnum>({{mbglStops}}, function.interpolationBase);
+
+ // Enumerations can only ever use interval stops.
+ mbgl::style::IntervalStops<MBGLType> intervalStops = {stops};
+
+ mbgl::style::CameraFunction<MBGLType> cameraFunction = {intervalStops};
+ return cameraFunction;
} else if (value) {
[NSException raise:@"MGLAbstractClassException" format:
@"The style value %@ cannot be applied to the style. "
@@ -103,95 +173,239 @@ public:
}
}
-private:
+private: // Private utilities for converting from mgl to mbgl values
- MGLStyleConstantValue<ObjCType> *toStyleConstantValue(const MBGLType mbglValue) {
- auto rawValue = toMGLRawStyleValue(mbglValue);
- return [MGLStyleConstantValue<ObjCType> valueWithRawValue:rawValue];
+ MBGLType toMBGLConstantValue(MGLStyleConstantValue<ObjCType> *value) {
+ MBGLType mbglValue;
+ getMBGLValue(value.rawValue, mbglValue);
+ return mbglValue;
}
- MGLStyleFunction<ObjCType> *toStyleFunction(const mbgl::style::Function<MBGLType> &mbglFunction) {
- const auto &mbglStops = mbglFunction.getStops();
- NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.size()];
- for (const auto &mbglStop : mbglStops) {
- auto rawValue = toMGLRawStyleValue(mbglStop.second);
- stops[@(mbglStop.first)] = [MGLStyleValue valueWithRawValue:rawValue];
+ /**
+ As hack to allow converting enum => string values, we accept a second, dummy parameter in
+ the toRawStyleSpecValue() methods for converting 'atomic' (non-style-function) values.
+ This allows us to use `std::enable_if` to test (at compile time) whether or not MBGLType is an Enum.
+ */
+ template <typename MBGLEnum = MBGLType,
+ class = typename std::enable_if<!std::is_enum<MBGLEnum>::value>::type,
+ typename MGLEnum = ObjCEnum,
+ class = typename std::enable_if<!std::is_enum<MGLEnum>::value>::type>
+ NSObject* toRawStyleSpecValue(NSObject *rawMGLValue, MBGLEnum &mbglValue) {
+ if ([rawMGLValue isKindOfClass:[NSValue class]]) {
+ const auto rawNSValue = (NSValue *)rawMGLValue;
+ if (strcmp([rawNSValue objCType], @encode(CGVector)) == 0) {
+ // offset [x, y]
+ std::array<float, 2> mglValue = rawNSValue.mgl_offsetArrayValue;
+ return [NSArray arrayWithObjects:@(mglValue[0]), @(mglValue[1]), nil];
+ }
}
- return [MGLStyleFunction<ObjCType> functionWithInterpolationBase:mbglFunction.getBase() stops:stops];
+ // noop pass-through plain NSObject-based items
+ return rawMGLValue;
}
-
+
template <typename MBGLEnum = MBGLType,
- class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
- typename MGLEnum = ObjCEnum,
- class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
- MGLStyleConstantValue<ObjCType> *toEnumStyleConstantValue(const MBGLEnum mbglValue) {
- auto str = mbgl::Enum<MBGLEnum>::toString(mbglValue);
- MGLEnum mglType = *mbgl::Enum<MGLEnum>::toEnum(str);
- return [MGLStyleConstantValue<ObjCType> valueWithRawValue:[NSValue value:&mglType withObjCType:@encode(MGLEnum)]];
- }
-
- NSNumber *toMGLRawStyleValue(const bool mbglStopValue) {
- return @(mbglStopValue);
+ class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
+ typename MGLEnum = ObjCEnum,
+ class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
+ NSString* toRawStyleSpecValue(ObjCType rawValue, MBGLEnum &mbglValue) {
+ MGLEnum mglEnum;
+ [rawValue getValue:&mglEnum];
+ return @(mbgl::Enum<MGLEnum>::toString(mglEnum));
}
- NSNumber *toMGLRawStyleValue(const float mbglStopValue) {
- return @(mbglStopValue);
+ NSObject* toRawStyleSpecValue(MGLColor *color, MBGLType &mbglValue) {
+ return @(color.mgl_color.stringify().c_str());
}
+
- NSString *toMGLRawStyleValue(const std::string &mbglStopValue) {
- return @(mbglStopValue.c_str());
+ NSObject* toRawStyleSpecValue(MGLStyleFunction<ObjCType>* styleFunction) {
+ NSMutableDictionary * rawFunction = [NSMutableDictionary new];
+ // interpolationMode => type
+ switch (styleFunction.interpolationMode) {
+ case MGLInterpolationModeExponential:
+ rawFunction[@"type"] = @"exponential";
+ break;
+ case MGLInterpolationModeInterval:
+ rawFunction[@"type"] = @"interval";
+ break;
+ case MGLInterpolationModeCategorical:
+ rawFunction[@"type"] = @"categorical";
+ break;
+ case MGLInterpolationModeIdentity:
+ rawFunction[@"type"] = @"identity";
+ break;
+ }
+
+ // interpolationBase => base
+ if (styleFunction.interpolationBase) {
+ rawFunction[@"base"] = @(styleFunction.interpolationBase);
+ }
+
+ // stops and default value
+ if ([styleFunction isKindOfClass:[MGLCameraStyleFunction class]]) {
+ // zoom-only function (no default value)
+ __block NSMutableArray *stops = [[NSMutableArray alloc] init];
+ [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleConstantValue<ObjCType> * _Nonnull outputValue, BOOL * _Nonnull stop) {
+ MBGLType dummyMbglValue;
+ NSArray *rawStop = @[zoomKey, toRawStyleSpecValue([outputValue rawValue], dummyMbglValue)];
+ [stops addObject:rawStop];
+ }];
+ rawFunction[@"stops"] = stops;
+
+ } else if ([styleFunction isKindOfClass:[MGLSourceStyleFunction class]]) {
+ auto sourceStyleFunction = (MGLSourceStyleFunction<ObjCType> *)styleFunction;
+ rawFunction[@"property"] = sourceStyleFunction.attributeName;
+ // property-only function
+ __block NSMutableArray *stops = [[NSMutableArray alloc] init];
+ [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSObject * _Nonnull propertyKey, MGLStyleConstantValue<ObjCType> * _Nonnull outputValue, BOOL * _Nonnull stop) {
+ MBGLType dummyMbglValue;
+ NSArray *rawStop = @[propertyKey, toRawStyleSpecValue([outputValue rawValue], dummyMbglValue)];
+ [stops addObject:rawStop];
+ }];
+ rawFunction[@"stops"] = stops;
+
+ // defaultValue => default
+ if (sourceStyleFunction.defaultValue) {
+ NSCAssert([sourceStyleFunction.defaultValue isKindOfClass:[MGLStyleConstantValue class]], @"Default value must be constant");
+ MBGLType dummyMbglValue;
+ rawFunction[@"default"] = toRawStyleSpecValue([(MGLStyleConstantValue<ObjCType> *)sourceStyleFunction.defaultValue rawValue], dummyMbglValue);
+ }
+ } else if ([styleFunction isKindOfClass:[MGLCompositeStyleFunction class]]) {
+ // zoom-and-property function
+ auto compositeStyleFunction = (MGLCompositeStyleFunction<ObjCType> *)styleFunction;
+ rawFunction[@"property"] = compositeStyleFunction.attributeName;
+
+ __block NSMutableArray *stops = [[NSMutableArray alloc] init];
+ [compositeStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, NSDictionary * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ for (NSObject *valueKey in stopValue.allKeys) {
+ NSDictionary *stopKey = @{
+ @"zoom": zoomKey,
+ @"value": valueKey
+ };
+ MGLStyleConstantValue<ObjCType> *outputValue = stopValue[valueKey];
+ NSCAssert([outputValue isKindOfClass:[MGLStyleConstantValue<ObjCType> class]], @"Stop outputs should be MGLStyleConstantValues");
+ MBGLType dummyMbglValue;
+ NSArray *rawStop = @[stopKey, toRawStyleSpecValue([outputValue rawValue], dummyMbglValue)];
+ [stops addObject:rawStop];
+ }
+ }];
+ rawFunction[@"stops"] = stops;
+
+ // defaultValue => default
+ if (compositeStyleFunction.defaultValue) {
+ NSCAssert([compositeStyleFunction.defaultValue isKindOfClass:[MGLStyleConstantValue class]], @"Default value must be constant");
+ MBGLType dummyMbglValue;
+ rawFunction[@"default"] = toRawStyleSpecValue([(MGLStyleConstantValue<ObjCType> *)compositeStyleFunction.defaultValue rawValue], dummyMbglValue);
+ }
+ }
+
+ return rawFunction;
}
-
- // Offsets
- NSValue *toMGLRawStyleValue(const std::array<float, 2> &mbglStopValue) {
- return [NSValue mgl_valueWithOffsetArray:mbglStopValue];
+
+ mbgl::style::CameraFunction<MBGLType> toMBGLExponentialCameraFunction(MGLStyleFunction<ObjCType> *styleFunction) {
+ __block std::map<float, MBGLType> stops = {};
+ [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
+ auto mbglStopValue = toPropertyValue(stopValue);
+ NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
+ stops[zoomKey.floatValue] = mbglStopValue.asConstant();
+ }];
+
+ // Camera function with Exponential stops
+ mbgl::style::ExponentialStops<MBGLType> exponentialStops = {stops, (float)styleFunction.interpolationBase};
+ mbgl::style::CameraFunction<MBGLType> cameraFunction = {exponentialStops};
+
+ return cameraFunction;
}
-
- // Padding
- NSValue *toMGLRawStyleValue(const std::array<float, 4> &mbglStopValue) {
- return [NSValue mgl_valueWithPaddingArray:mbglStopValue];
+
+ mbgl::style::CameraFunction<MBGLType> toMBGLIntervalCameraFunction(MGLStyleFunction<ObjCType> *styleFunction) {
+ __block std::map<float, MBGLType> stops = {};
+ [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
+ auto mbglStopValue = toPropertyValue(stopValue);
+ NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
+ stops[zoomKey.floatValue] = mbglStopValue.asConstant();
+ }];
+
+ // Camera function with Interval stops
+ mbgl::style::IntervalStops<MBGLType> intervalStops = {stops};
+ mbgl::style::CameraFunction<MBGLType> cameraFunction = {intervalStops};
+
+ return cameraFunction;
}
-
- MGLColor *toMGLRawStyleValue(const mbgl::Color mbglStopValue) {
- return [MGLColor mgl_colorWithColor:mbglStopValue];
+
+ mbgl::style::SourceFunction<MBGLType> toMBGLCategoricalSourceFunction(MGLSourceStyleFunction<ObjCType> *sourceStyleFunction) {
+ __block std::map<mbgl::style::CategoricalValue, MBGLType> stops = {};
+ [sourceStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(id categoryKey, MGLStyleValue<ObjCType> *stopValue, BOOL *stop) {
+ NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
+ auto mbglStopValue = toPropertyValue(stopValue);
+ NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
+
+ if ([categoryKey isKindOfClass:[NSString class]]) {
+ const std::string& convertedValueKey = [((NSString *)categoryKey) UTF8String];
+ stops[mbgl::style::CategoricalValue(convertedValueKey)] = mbglStopValue.asConstant();
+ } else if ([categoryKey isKindOfClass:[NSNumber class]]) {
+ NSNumber *key = (NSNumber *)categoryKey;
+ if ((strcmp([key objCType], @encode(char)) == 0) ||
+ (strcmp([key objCType], @encode(BOOL)) == 0)) {
+ stops[mbgl::style::CategoricalValue((bool)[key boolValue])] = mbglStopValue.asConstant();
+ } else if (strcmp([key objCType], @encode(double)) == 0 ||
+ strcmp([key objCType], @encode(float)) == 0) {
+ NSCAssert(mbglStopValue.isConstant(), @"Categorical stop keys must be strings, booleans, or integers");
+ } else if ([key compare:@(0)] == NSOrderedDescending ||
+ [key compare:@(0)] == NSOrderedSame ||
+ [key compare:@(0)] == NSOrderedAscending) {
+ stops[mbgl::style::CategoricalValue((int64_t)[key integerValue])] = mbglStopValue.asConstant();
+ }
+ }
+ }];
+ mbgl::style::CategoricalStops<MBGLType> categoricalStops = {stops};
+ mbgl::style::SourceFunction<MBGLType> sourceFunction = {sourceStyleFunction.attributeName.UTF8String, categoricalStops};
+ setDefaultMBGLValue(sourceStyleFunction, sourceFunction);
+ return sourceFunction;
}
-
- ObjCType toMGLRawStyleValue(const std::vector<MBGLElement> &mbglStopValue) {
- NSMutableArray *array = [NSMutableArray arrayWithCapacity:mbglStopValue.size()];
- for (const auto &mbglElement: mbglStopValue) {
- [array addObject:toMGLRawStyleValue(mbglElement)];
+
+ void setDefaultMBGLValue(MGLSourceStyleFunction<ObjCType> *sourceStyleFunction, mbgl::style::SourceFunction<MBGLType> &sourceFunction) {
+ if (sourceStyleFunction.defaultValue) {
+ NSCAssert([sourceStyleFunction.defaultValue isKindOfClass:[MGLStyleConstantValue class]], @"Default value must be constant");
+ MBGLType mbglValue;
+ id mglValue = [(MGLStyleConstantValue<ObjCType> *)sourceStyleFunction.defaultValue rawValue];
+ getMBGLValue(mglValue, mbglValue);
+ sourceFunction.defaultValue = mbglValue;
}
- return array;
}
-private:
-
+ // Bool
void getMBGLValue(NSNumber *rawValue, bool &mbglValue) {
mbglValue = !!rawValue.boolValue;
}
-
+
+ // Float
void getMBGLValue(NSNumber *rawValue, float &mbglValue) {
mbglValue = rawValue.floatValue;
}
-
+
+ // String
void getMBGLValue(NSString *rawValue, std::string &mbglValue) {
mbglValue = rawValue.UTF8String;
}
-
+
// Offsets
void getMBGLValue(NSValue *rawValue, std::array<float, 2> &mbglValue) {
mbglValue = rawValue.mgl_offsetArrayValue;
}
-
+
// Padding
void getMBGLValue(NSValue *rawValue, std::array<float, 4> &mbglValue) {
mbglValue = rawValue.mgl_paddingArrayValue;
}
-
+
+ // Color
void getMBGLValue(MGLColor *rawValue, mbgl::Color &mbglValue) {
mbglValue = rawValue.mgl_color;
}
-
+
+ // Array
void getMBGLValue(ObjCType rawValue, std::vector<MBGLElement> &mbglValue) {
mbglValue.reserve(rawValue.count);
for (id obj in rawValue) {
@@ -212,4 +426,267 @@ private:
auto str = mbgl::Enum<MGLEnum>::toString(mglEnum);
mbglValue = *mbgl::Enum<MBGLEnum>::toEnum(str);
}
+
+private: // Private utilities for converting from mbgl to mgl values
+
+ // Bool
+ static NSNumber *toMGLRawStyleValue(const bool mbglStopValue) {
+ return @(mbglStopValue);
+ }
+
+ // Float
+ static NSNumber *toMGLRawStyleValue(const float mbglStopValue) {
+ return @(mbglStopValue);
+ }
+
+ // Integer
+ static NSNumber *toMGLRawStyleValue(const int64_t mbglStopValue) {
+ return @(mbglStopValue);
+ }
+
+ // String
+ static NSString *toMGLRawStyleValue(const std::string &mbglStopValue) {
+ return @(mbglStopValue.c_str());
+ }
+
+ // Offsets
+ static NSValue *toMGLRawStyleValue(const std::array<float, 2> &mbglStopValue) {
+ return [NSValue mgl_valueWithOffsetArray:mbglStopValue];
+ }
+
+ // Padding
+ static NSValue *toMGLRawStyleValue(const std::array<float, 4> &mbglStopValue) {
+ return [NSValue mgl_valueWithPaddingArray:mbglStopValue];
+ }
+
+ // Color
+ static MGLColor *toMGLRawStyleValue(const mbgl::Color mbglStopValue) {
+ return [MGLColor mgl_colorWithColor:mbglStopValue];
+ }
+
+ // Array
+ static ObjCType toMGLRawStyleValue(const std::vector<MBGLElement> &mbglStopValue) {
+ NSMutableArray *array = [NSMutableArray arrayWithCapacity:mbglStopValue.size()];
+ for (const auto &mbglElement: mbglStopValue) {
+ [array addObject:toMGLRawStyleValue(mbglElement)];
+ }
+ return array;
+ }
+
+ // Enumerations
+ template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum>
+ static NSValue *toMGLRawStyleValue(const MBGLEnum &value) {
+ auto str = mbgl::Enum<MBGLEnum>::toString(value);
+ MGLEnum mglType = *mbgl::Enum<MGLEnum>::toEnum(str);
+ return [NSValue value:&mglType withObjCType:@encode(MGLEnum)];
+ }
+
+ // Converts mbgl stops to an equivilent NSDictionary for mgl
+ static NSMutableDictionary *toConvertedStops(const std::map<float, MBGLType> &mbglStops) {
+ NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.size()];
+ for (const auto &mbglStop : mbglStops) {
+ auto rawValue = toMGLRawStyleValue(mbglStop.second);
+ stops[@(mbglStop.first)] = [MGLStyleValue valueWithRawValue:rawValue];
+ }
+ return stops;
+ }
+
+ // Converts mbgl interval stop categorical values to an equivilant object for mgl
+ class CategoricalValueVisitor {
+ public:
+ id operator()(const bool value) {
+ return toMGLRawStyleValue(value);
+ }
+
+ id operator()(const int64_t value) {
+ return toMGLRawStyleValue(value);
+ }
+
+ id operator()(const std::string value) {
+ return toMGLRawStyleValue(value);
+ }
+ };
+
+ // Converts all types of mbgl property values containing enumerations into an equivilant mgl style value
+ template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum>
+ class EnumPropertyValueEvaluator {
+ public:
+ id operator()(const mbgl::style::Undefined) const {
+ return nil;
+ }
+
+ id operator()(const MBGLEnum &value) const {
+ auto str = mbgl::Enum<MBGLEnum>::toString(value);
+ MGLEnum mglType = *mbgl::Enum<MGLEnum>::toEnum(str);
+ return [MGLStyleConstantValue<ObjCType> valueWithRawValue:[NSValue value:&mglType withObjCType:@encode(MGLEnum)]];
+ }
+
+ id operator()(const mbgl::style::CameraFunction<MBGLEnum> &mbglValue) const {
+ CameraFunctionStopsVisitor visitor;
+ return apply_visitor(visitor, mbglValue.stops);
+ }
+ };
+
+ // Converts all possible mbgl camera function stops into an equivilant mgl style value
+ class CameraFunctionStopsVisitor {
+ public:
+ id operator()(const mbgl::style::ExponentialStops<MBGLType> &mbglStops) {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential
+ stops:toConvertedStops(mbglStops.stops)
+ options:@{MGLStyleFunctionOptionInterpolationBase: @(mbglStops.base)}];
+ }
+
+ id operator()(const mbgl::style::IntervalStops<MBGLType> &mbglStops) {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeInterval
+ stops:toConvertedStops(mbglStops.stops)
+ options:nil];
+ }
+ };
+
+ // Converts a source function and all possible mbgl source function stops into an equivilant mgl style value
+ class SourceFunctionStopsVisitor {
+ public:
+ id operator()(const mbgl::style::ExponentialStops<MBGLType> &mbglStops) {
+ MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential
+ stops:toConvertedStops(mbglStops.stops)
+ attributeName:@(mbglFunction.property.c_str())
+ options:@{MGLStyleFunctionOptionInterpolationBase: @(mbglStops.base)}];
+ if (mbglFunction.defaultValue) {
+ sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return sourceFunction;
+ }
+
+ id operator()(const mbgl::style::IntervalStops<MBGLType> &mbglStops) {
+ MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeInterval
+ stops:toConvertedStops(mbglStops.stops)
+ attributeName:@(mbglFunction.property.c_str())
+ options:nil];
+ if (mbglFunction.defaultValue) {
+ sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return sourceFunction;
+ }
+
+ id operator()(const mbgl::style::CategoricalStops<MBGLType> &mbglStops) {
+ NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()];
+ for (const auto &mbglStop : mbglStops.stops) {
+ auto categoricalValue = mbglStop.first;
+ auto rawValue = toMGLRawStyleValue(mbglStop.second);
+ CategoricalValueVisitor categoricalValueVisitor;
+ id stopKey = apply_visitor(categoricalValueVisitor, categoricalValue);
+ stops[stopKey] = [MGLStyleValue valueWithRawValue:rawValue];
+ }
+
+ MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeCategorical
+ stops:stops
+ attributeName:@(mbglFunction.property.c_str())
+ options:nil];
+ if (mbglFunction.defaultValue) {
+ sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return sourceFunction;
+
+ }
+
+ id operator()(const mbgl::style::IdentityStops<MBGLType> &mbglStops) {
+ MGLSourceStyleFunction *sourceFunction = [MGLSourceStyleFunction functionWithInterpolationMode:MGLInterpolationModeIdentity
+ stops:nil
+ attributeName:@(mbglFunction.property.c_str()) options:nil];
+ if (mbglFunction.defaultValue) {
+ sourceFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return sourceFunction;
+ }
+
+ const mbgl::style::SourceFunction<MBGLType> &mbglFunction;
+ };
+
+ // Converts a composite function and all possible mbgl stops into an equivilant mgl style value
+ class CompositeFunctionStopsVisitor {
+ public:
+ id operator()(const mbgl::style::CompositeExponentialStops<MBGLType> &mbglStops) {
+ NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()];
+ for (auto const& outerStop: mbglStops.stops) {
+ stops[@(outerStop.first)] = toConvertedStops(outerStop.second);
+ }
+ MGLCompositeStyleFunction *compositeFunction = [MGLCompositeStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential
+ stops:stops
+ attributeName:@(mbglFunction.property.c_str())
+ options:@{MGLStyleFunctionOptionInterpolationBase: @(mbglStops.base)}];
+ if (mbglFunction.defaultValue) {
+ compositeFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return compositeFunction;
+ }
+
+ id operator()(const mbgl::style::CompositeIntervalStops<MBGLType> &mbglStops) {
+ NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()];
+ for (auto const& outerStop: mbglStops.stops) {
+ stops[@(outerStop.first)] = toConvertedStops(outerStop.second);
+ }
+ MGLCompositeStyleFunction *compositeFunction = [MGLCompositeStyleFunction functionWithInterpolationMode:MGLInterpolationModeInterval
+ stops:stops
+ attributeName:@(mbglFunction.property.c_str())
+ options:nil];
+ if (mbglFunction.defaultValue) {
+ compositeFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return compositeFunction;
+ }
+
+ id operator()(const mbgl::style::CompositeCategoricalStops<MBGLType> &mbglStops) {
+ NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.stops.size()];
+ for (auto const& outerStop: mbglStops.stops) {
+ NSMutableDictionary *innerStops = [NSMutableDictionary dictionaryWithCapacity:outerStop.second.size()];
+ for (const auto &mbglStop : outerStop.second) {
+ auto categoricalValue = mbglStop.first;
+ auto rawValue = toMGLRawStyleValue(mbglStop.second);
+ CategoricalValueVisitor categoricalValueVisitor;
+ id stopKey = apply_visitor(categoricalValueVisitor, categoricalValue);
+ innerStops[stopKey] = [MGLStyleValue valueWithRawValue:rawValue];
+ }
+ stops[@(outerStop.first)] = innerStops;
+ }
+
+ MGLCompositeStyleFunction *compositeFunction = [MGLCompositeStyleFunction functionWithInterpolationMode:MGLInterpolationModeCategorical
+ stops:stops attributeName:@(mbglFunction.property.c_str())
+ options:nil];
+ if (mbglFunction.defaultValue) {
+ compositeFunction.defaultValue = [MGLStyleValue valueWithRawValue:toMGLRawStyleValue(*mbglFunction.defaultValue)];
+ }
+ return compositeFunction;
+ }
+
+ const mbgl::style::CompositeFunction<MBGLType> &mbglFunction;
+ };
+
+
+ // Converts all types of mbgl property values that don't contain enumerations into an equivilant mgl style value
+ class PropertyValueEvaluator {
+ public:
+ id operator()(const mbgl::style::Undefined) const {
+ return nil;
+ }
+
+ id operator()(const MBGLType &value) const {
+ auto rawValue = toMGLRawStyleValue(value);
+ return [MGLStyleConstantValue<ObjCType> valueWithRawValue:rawValue];
+ }
+
+ id operator()(const mbgl::style::CameraFunction<MBGLType> &mbglValue) const {
+ CameraFunctionStopsVisitor visitor;
+ return apply_visitor(visitor, mbglValue.stops);
+ }
+
+ id operator()(const mbgl::style::SourceFunction<MBGLType> &mbglValue) const {
+ SourceFunctionStopsVisitor visitor { mbglValue };
+ return apply_visitor(visitor, mbglValue.stops);
+ }
+
+ MGLCompositeStyleFunction<ObjCType> * operator()(const mbgl::style::CompositeFunction<MBGLType> &mbglValue) const {
+ CompositeFunctionStopsVisitor visitor { mbglValue };
+ return apply_visitor(visitor, mbglValue.stops);
+ }
+ };
};
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index c693978ab6..d2892f9627 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -1,6 +1,7 @@
-// This file is generated.
+// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLVectorStyleLayer.h"
@@ -9,7 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
In combination with `symbolPlacement`, determines the rotation behavior of
icons.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.iconRotationAlignment`
property.
*/
@@ -36,7 +37,7 @@ typedef NS_ENUM(NSUInteger, MGLIconRotationAlignment) {
/**
Scales the icon to fit around the associated text.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.iconTextFit`
property.
*/
@@ -61,7 +62,7 @@ typedef NS_ENUM(NSUInteger, MGLIconTextFit) {
/**
Label placement relative to its geometry.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.symbolPlacement`
property.
*/
@@ -79,7 +80,7 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) {
/**
Part of the text placed closest to the anchor.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.textAnchor`
property.
*/
@@ -124,7 +125,7 @@ typedef NS_ENUM(NSUInteger, MGLTextAnchor) {
/**
Text justification options.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.textJustification`
property.
*/
@@ -145,7 +146,7 @@ typedef NS_ENUM(NSUInteger, MGLTextJustification) {
/**
Orientation of text when map is pitched.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.textPitchAlignment`
property.
*/
@@ -167,7 +168,7 @@ typedef NS_ENUM(NSUInteger, MGLTextPitchAlignment) {
/**
In combination with `symbolPlacement`, determines the rotation behavior of the
individual glyphs forming the text.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.textRotationAlignment`
property.
*/
@@ -194,7 +195,7 @@ typedef NS_ENUM(NSUInteger, MGLTextRotationAlignment) {
/**
Specifies how to capitalize text.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.textTransform`
property.
*/
@@ -215,7 +216,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTransform) {
/**
Controls the translation reference point.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.iconTranslationAnchor`
property.
*/
@@ -232,7 +233,7 @@ typedef NS_ENUM(NSUInteger, MGLIconTranslationAnchor) {
/**
Controls the translation reference point.
-
+
Values of this type are used in the `MGLSymbolStyleLayer.textTranslationAnchor`
property.
*/
@@ -254,15 +255,15 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
Use a symbol style layer to configure the visual appearance of labels for
features in vector tiles loaded by an `MGLVectorSource` object or `MGLShape` or
`MGLFeature` instances in an `MGLShapeSource` object.
-
+
You can access an existing symbol style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
otherwise, find it using the `MGLStyle.layers` property. You can also create a
new symbol style layer and add it to the style using a method such as
`-[MGLStyle addLayer:]`.
-
+
### Example
-
+
```swift
let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois)
layer.sourceLayerIdentifier = "pois"
@@ -276,6 +277,7 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
mapView.style?.addLayer(layer)
```
*/
+MGL_EXPORT
@interface MGLSymbolStyleLayer : MGLVectorStyleLayer
#pragma mark - Accessing the Layout Attributes
@@ -294,6 +296,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-allow-overlap"><code>icon-allow-overlap</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconAllowsOverlap;
@@ -313,6 +321,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-ignore-placement"><code>icon-ignore-placement</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconIgnoresPlacement;
@@ -325,6 +339,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-image"><code>icon-image</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *iconImageName;
@@ -341,6 +361,22 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconOffset;
#else
@@ -353,6 +389,22 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconOffset;
#endif
@@ -367,6 +419,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`, and
`text` is non-`nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable, getter=isIconOptional) MGLStyleValue<NSNumber *> *iconOptional;
@@ -382,6 +440,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconPadding;
@@ -400,6 +465,22 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-rotate"><code>icon-rotate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconRotation;
@@ -416,6 +497,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconRotationAlignment;
@@ -432,6 +519,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-size"><code>icon-size</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconScale;
@@ -447,6 +541,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`, and
`text` is non-`nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTextFit;
@@ -464,6 +564,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
`text` is non-`nil`, and `iconTextFit` is set to an `MGLStyleValue` object
containing an `NSValue` object containing `MGLIconTextFitBoth`,
`MGLIconTextFitWidth`, or `MGLIconTextFitHeight`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTextFitPadding;
#else
@@ -480,6 +587,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
`text` is non-`nil`, and `iconTextFit` is set to an `MGLStyleValue` object
containing an `NSValue` object containing `MGLIconTextFitBoth`,
`MGLIconTextFitWidth`, or `MGLIconTextFitHeight`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTextFitPadding;
#endif
@@ -500,6 +614,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-keep-upright"><code>icon-keep-upright</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *keepsIconUpright;
@@ -523,6 +643,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-keep-upright"><code>text-keep-upright</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *keepsTextUpright;
@@ -545,6 +671,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-max-angle"><code>text-max-angle</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *maximumTextAngle;
@@ -566,6 +699,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-max-width"><code>text-max-width</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *maximumTextWidth;
@@ -585,6 +725,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-symbol-avoid-edges"><code>symbol-avoid-edges</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *symbolAvoidsEdges;
@@ -597,6 +743,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
The default value of this property is an `MGLStyleValue` object containing an
`NSValue` object containing `MGLSymbolPlacementPoint`. Set this property to
`nil` to reset it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *symbolPlacement;
@@ -612,12 +764,20 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `symbolPlacement` is set to an
`MGLStyleValue` object containing an `NSValue` object containing
`MGLSymbolPlacementLine`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *symbolSpacing;
/**
Value to use for a text label. Feature properties are specified using tokens
- like {field_name}.
+ like {field_name}. (Token replacement is only supported for literal
+ `textField` values--not for property functions.)
The default value of this property is an `MGLStyleValue` object containing the
empty string. Set this property to `nil` to reset it to the default value.
@@ -625,6 +785,22 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-field"><code>text-field</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *text;
@@ -645,6 +821,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-allow-overlap"><code>text-allow-overlap</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textAllowsOverlap;
@@ -660,6 +842,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textAnchor;
@@ -686,6 +874,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-font"><code>text-font</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSArray<NSString *> *> *textFontNames;
@@ -707,6 +901,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-size"><code>text-size</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textFontSize;
@@ -726,6 +927,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-ignore-placement"><code>text-ignore-placement</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textIgnoresPlacement;
@@ -745,6 +952,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-justify"><code>text-justify</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textJustification;
@@ -762,6 +975,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textLetterSpacing;
@@ -776,6 +996,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textLineHeight;
@@ -791,6 +1018,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textOffset;
#else
@@ -805,6 +1039,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textOffset;
#endif
@@ -819,6 +1060,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`, and
`iconImageName` is non-`nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable, getter=isTextOptional) MGLStyleValue<NSNumber *> *textOptional;
@@ -834,6 +1081,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textPadding;
@@ -846,6 +1100,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textPitchAlignment;
@@ -864,6 +1124,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-text-rotate"><code>text-rotate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textRotation;
@@ -880,6 +1147,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textRotationAlignment;
@@ -892,6 +1165,22 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textTransform;
@@ -908,6 +1197,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *iconColor;
#else
@@ -921,6 +1217,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *iconColor;
#endif
@@ -936,6 +1239,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloBlur;
@@ -950,6 +1260,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *iconHaloColor;
#else
@@ -963,6 +1280,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *iconHaloColor;
#endif
@@ -978,6 +1302,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloWidth;
@@ -990,6 +1321,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconOpacity;
@@ -1009,6 +1347,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-icon-translate"><code>icon-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTranslation;
#else
@@ -1027,6 +1372,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-icon-translate"><code>icon-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTranslation;
#endif
@@ -1046,6 +1398,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-icon-translate-anchor"><code>icon-translate-anchor</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTranslationAnchor;
@@ -1061,6 +1419,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *textColor;
#else
@@ -1073,6 +1438,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *textColor;
#endif
@@ -1088,6 +1460,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloBlur;
@@ -1101,6 +1480,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *textHaloColor;
#else
@@ -1113,6 +1499,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *textHaloColor;
#endif
@@ -1129,6 +1522,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloWidth;
@@ -1141,6 +1541,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textOpacity;
@@ -1160,6 +1567,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-text-translate"><code>text-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textTranslation;
#else
@@ -1178,6 +1592,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-text-translate"><code>text-translate</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textTranslation;
#endif
@@ -1197,6 +1618,12 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-text-translate-anchor"><code>text-translate-anchor</code></a>
layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLStyleConstantValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textTranslationAnchor;
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index c7ba9d7dc5..066a0190fb 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLSource.h"
#import "MGLMapView_Private.h"
@@ -8,7 +8,9 @@
#import "MGLStyleValue_Private.h"
#import "MGLSymbolStyleLayer.h"
+#include <mbgl/map/map.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
+
namespace mbgl {
MBGL_DEFINE_ENUM(MGLIconRotationAlignment, {
@@ -111,7 +113,7 @@ namespace mbgl {
- (NSString *)sourceIdentifier
{
MGLAssertStyleLayerIsValid();
-
+
return @(self.rawLayer->getSourceID().c_str());
}
@@ -195,7 +197,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)iconAllowsOverlap {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconAllowOverlap() ?: self.rawLayer->getDefaultIconAllowOverlap();
+ auto propertyValue = self.rawLayer->getIconAllowOverlap();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconAllowOverlap());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -216,7 +221,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)iconIgnoresPlacement {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconIgnorePlacement() ?: self.rawLayer->getDefaultIconIgnorePlacement();
+ auto propertyValue = self.rawLayer->getIconIgnorePlacement();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconIgnorePlacement());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -237,7 +245,10 @@ namespace mbgl {
- (MGLStyleValue<NSString *> *)iconImageName {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconImage() ?: self.rawLayer->getDefaultIconImage();
+ auto propertyValue = self.rawLayer->getIconImage();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultIconImage());
+ }
return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
@@ -251,15 +262,18 @@ namespace mbgl {
- (void)setIconOffset:(MGLStyleValue<NSValue *> *)iconOffset {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(iconOffset);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toDataDrivenPropertyValue(iconOffset);
self.rawLayer->setIconOffset(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconOffset {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconOffset() ?: self.rawLayer->getDefaultIconOffset();
- return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getIconOffset();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconOffset());
+ }
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconOptional:(MGLStyleValue<NSNumber *> *)iconOptional {
@@ -272,36 +286,45 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)isIconOptional {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconOptional() ?: self.rawLayer->getDefaultIconOptional();
+ auto propertyValue = self.rawLayer->getIconOptional();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconOptional());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconPadding:(MGLStyleValue<NSNumber *> *)iconPadding {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconPadding);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconPadding);
self.rawLayer->setIconPadding(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconPadding {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconPadding() ?: self.rawLayer->getDefaultIconPadding();
+ auto propertyValue = self.rawLayer->getIconPadding();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconPadding());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconRotation:(MGLStyleValue<NSNumber *> *)iconRotation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconRotation);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(iconRotation);
self.rawLayer->setIconRotate(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconRotation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconRotate() ?: self.rawLayer->getDefaultIconRotate();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getIconRotate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconRotate());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconRotate:(MGLStyleValue<NSNumber *> *)iconRotate {
@@ -321,21 +344,27 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)iconRotationAlignment {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconRotationAlignment() ?: self.rawLayer->getDefaultIconRotationAlignment();
+ auto propertyValue = self.rawLayer->getIconRotationAlignment();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLIconRotationAlignment>().toEnumStyleValue(self.rawLayer->getDefaultIconRotationAlignment());
+ }
return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLIconRotationAlignment>().toEnumStyleValue(propertyValue);
}
- (void)setIconScale:(MGLStyleValue<NSNumber *> *)iconScale {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconScale);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconScale);
self.rawLayer->setIconSize(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconScale {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconSize() ?: self.rawLayer->getDefaultIconSize();
+ auto propertyValue = self.rawLayer->getIconSize();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconSize());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -356,21 +385,27 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)iconTextFit {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconTextFit() ?: self.rawLayer->getDefaultIconTextFit();
+ auto propertyValue = self.rawLayer->getIconTextFit();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::IconTextFitType, NSValue *, mbgl::style::IconTextFitType, MGLIconTextFit>().toEnumStyleValue(self.rawLayer->getDefaultIconTextFit());
+ }
return MGLStyleValueTransformer<mbgl::style::IconTextFitType, NSValue *, mbgl::style::IconTextFitType, MGLIconTextFit>().toEnumStyleValue(propertyValue);
}
- (void)setIconTextFitPadding:(MGLStyleValue<NSValue *> *)iconTextFitPadding {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 4>, NSValue *>().toPropertyValue(iconTextFitPadding);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 4>, NSValue *>().toInterpolatablePropertyValue(iconTextFitPadding);
self.rawLayer->setIconTextFitPadding(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconTextFitPadding {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconTextFitPadding() ?: self.rawLayer->getDefaultIconTextFitPadding();
+ auto propertyValue = self.rawLayer->getIconTextFitPadding();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 4>, NSValue *>().toStyleValue(self.rawLayer->getDefaultIconTextFitPadding());
+ }
return MGLStyleValueTransformer<std::array<float, 4>, NSValue *>().toStyleValue(propertyValue);
}
@@ -384,7 +419,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)keepsIconUpright {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconKeepUpright() ?: self.rawLayer->getDefaultIconKeepUpright();
+ auto propertyValue = self.rawLayer->getIconKeepUpright();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconKeepUpright());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -405,7 +443,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)keepsTextUpright {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextKeepUpright() ?: self.rawLayer->getDefaultTextKeepUpright();
+ auto propertyValue = self.rawLayer->getTextKeepUpright();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextKeepUpright());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -419,14 +460,17 @@ namespace mbgl {
- (void)setMaximumTextAngle:(MGLStyleValue<NSNumber *> *)maximumTextAngle {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(maximumTextAngle);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(maximumTextAngle);
self.rawLayer->setTextMaxAngle(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)maximumTextAngle {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextMaxAngle() ?: self.rawLayer->getDefaultTextMaxAngle();
+ auto propertyValue = self.rawLayer->getTextMaxAngle();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextMaxAngle());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -440,14 +484,17 @@ namespace mbgl {
- (void)setMaximumTextWidth:(MGLStyleValue<NSNumber *> *)maximumTextWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(maximumTextWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(maximumTextWidth);
self.rawLayer->setTextMaxWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)maximumTextWidth {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextMaxWidth() ?: self.rawLayer->getDefaultTextMaxWidth();
+ auto propertyValue = self.rawLayer->getTextMaxWidth();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextMaxWidth());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -468,7 +515,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)symbolAvoidsEdges {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getSymbolAvoidEdges() ?: self.rawLayer->getDefaultSymbolAvoidEdges();
+ auto propertyValue = self.rawLayer->getSymbolAvoidEdges();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultSymbolAvoidEdges());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -489,36 +539,45 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)symbolPlacement {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getSymbolPlacement() ?: self.rawLayer->getDefaultSymbolPlacement();
+ auto propertyValue = self.rawLayer->getSymbolPlacement();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::SymbolPlacementType, NSValue *, mbgl::style::SymbolPlacementType, MGLSymbolPlacement>().toEnumStyleValue(self.rawLayer->getDefaultSymbolPlacement());
+ }
return MGLStyleValueTransformer<mbgl::style::SymbolPlacementType, NSValue *, mbgl::style::SymbolPlacementType, MGLSymbolPlacement>().toEnumStyleValue(propertyValue);
}
- (void)setSymbolSpacing:(MGLStyleValue<NSNumber *> *)symbolSpacing {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(symbolSpacing);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(symbolSpacing);
self.rawLayer->setSymbolSpacing(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)symbolSpacing {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getSymbolSpacing() ?: self.rawLayer->getDefaultSymbolSpacing();
+ auto propertyValue = self.rawLayer->getSymbolSpacing();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultSymbolSpacing());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setText:(MGLStyleValue<NSString *> *)text {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(text);
+ auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toDataDrivenPropertyValue(text);
self.rawLayer->setTextField(mbglValue);
}
- (MGLStyleValue<NSString *> *)text {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextField() ?: self.rawLayer->getDefaultTextField();
- return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getTextField();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::string, NSString *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextField());
+ }
+ return MGLStyleValueTransformer<std::string, NSString *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextField:(MGLStyleValue<NSString *> *)textField {
@@ -538,7 +597,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)textAllowsOverlap {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextAllowOverlap() ?: self.rawLayer->getDefaultTextAllowOverlap();
+ auto propertyValue = self.rawLayer->getTextAllowOverlap();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextAllowOverlap());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -559,7 +621,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)textAnchor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextAnchor() ?: self.rawLayer->getDefaultTextAnchor();
+ auto propertyValue = self.rawLayer->getTextAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toEnumStyleValue(self.rawLayer->getDefaultTextAnchor());
+ }
return MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toEnumStyleValue(propertyValue);
}
@@ -573,7 +638,10 @@ namespace mbgl {
- (MGLStyleValue<NSArray<NSString *> *> *)textFontNames {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextFont() ?: self.rawLayer->getDefaultTextFont();
+ auto propertyValue = self.rawLayer->getTextFont();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::vector<std::string>, NSArray<NSString *> *, std::string>().toStyleValue(self.rawLayer->getDefaultTextFont());
+ }
return MGLStyleValueTransformer<std::vector<std::string>, NSArray<NSString *> *, std::string>().toStyleValue(propertyValue);
}
@@ -587,14 +655,17 @@ namespace mbgl {
- (void)setTextFontSize:(MGLStyleValue<NSNumber *> *)textFontSize {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textFontSize);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textFontSize);
self.rawLayer->setTextSize(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textFontSize {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextSize() ?: self.rawLayer->getDefaultTextSize();
+ auto propertyValue = self.rawLayer->getTextSize();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextSize());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -615,7 +686,10 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)textIgnoresPlacement {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextIgnorePlacement() ?: self.rawLayer->getDefaultTextIgnorePlacement();
+ auto propertyValue = self.rawLayer->getTextIgnorePlacement();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextIgnorePlacement());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
@@ -636,7 +710,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)textJustification {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextJustify() ?: self.rawLayer->getDefaultTextJustify();
+ auto propertyValue = self.rawLayer->getTextJustify();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TextJustifyType, NSValue *, mbgl::style::TextJustifyType, MGLTextJustification>().toEnumStyleValue(self.rawLayer->getDefaultTextJustify());
+ }
return MGLStyleValueTransformer<mbgl::style::TextJustifyType, NSValue *, mbgl::style::TextJustifyType, MGLTextJustification>().toEnumStyleValue(propertyValue);
}
@@ -650,42 +727,51 @@ namespace mbgl {
- (void)setTextLetterSpacing:(MGLStyleValue<NSNumber *> *)textLetterSpacing {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textLetterSpacing);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textLetterSpacing);
self.rawLayer->setTextLetterSpacing(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textLetterSpacing {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextLetterSpacing() ?: self.rawLayer->getDefaultTextLetterSpacing();
+ auto propertyValue = self.rawLayer->getTextLetterSpacing();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextLetterSpacing());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextLineHeight:(MGLStyleValue<NSNumber *> *)textLineHeight {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textLineHeight);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textLineHeight);
self.rawLayer->setTextLineHeight(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textLineHeight {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextLineHeight() ?: self.rawLayer->getDefaultTextLineHeight();
+ auto propertyValue = self.rawLayer->getTextLineHeight();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextLineHeight());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextOffset:(MGLStyleValue<NSValue *> *)textOffset {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(textOffset);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(textOffset);
self.rawLayer->setTextOffset(mbglValue);
}
- (MGLStyleValue<NSValue *> *)textOffset {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextOffset() ?: self.rawLayer->getDefaultTextOffset();
+ auto propertyValue = self.rawLayer->getTextOffset();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultTextOffset());
+ }
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
@@ -699,21 +785,27 @@ namespace mbgl {
- (MGLStyleValue<NSNumber *> *)isTextOptional {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextOptional() ?: self.rawLayer->getDefaultTextOptional();
+ auto propertyValue = self.rawLayer->getTextOptional();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextOptional());
+ }
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextPadding:(MGLStyleValue<NSNumber *> *)textPadding {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textPadding);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textPadding);
self.rawLayer->setTextPadding(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textPadding {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextPadding() ?: self.rawLayer->getDefaultTextPadding();
+ auto propertyValue = self.rawLayer->getTextPadding();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextPadding());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -727,21 +819,27 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)textPitchAlignment {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextPitchAlignment() ?: self.rawLayer->getDefaultTextPitchAlignment();
+ auto propertyValue = self.rawLayer->getTextPitchAlignment();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextPitchAlignment>().toEnumStyleValue(self.rawLayer->getDefaultTextPitchAlignment());
+ }
return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextPitchAlignment>().toEnumStyleValue(propertyValue);
}
- (void)setTextRotation:(MGLStyleValue<NSNumber *> *)textRotation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textRotation);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textRotation);
self.rawLayer->setTextRotate(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textRotation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextRotate() ?: self.rawLayer->getDefaultTextRotate();
+ auto propertyValue = self.rawLayer->getTextRotate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextRotate());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
@@ -762,22 +860,28 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)textRotationAlignment {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextRotationAlignment() ?: self.rawLayer->getDefaultTextRotationAlignment();
+ auto propertyValue = self.rawLayer->getTextRotationAlignment();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextRotationAlignment>().toEnumStyleValue(self.rawLayer->getDefaultTextRotationAlignment());
+ }
return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextRotationAlignment>().toEnumStyleValue(propertyValue);
}
- (void)setTextTransform:(MGLStyleValue<NSValue *> *)textTransform {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toEnumPropertyValue(textTransform);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toDataDrivenPropertyValue(textTransform);
self.rawLayer->setTextTransform(mbglValue);
}
- (MGLStyleValue<NSValue *> *)textTransform {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextTransform() ?: self.rawLayer->getDefaultTextTransform();
- return MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toEnumStyleValue(propertyValue);
+ auto propertyValue = self.rawLayer->getTextTransform();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextTransform());
+ }
+ return MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toDataDrivenStyleValue(propertyValue);
}
#pragma mark - Accessing the Paint Attributes
@@ -785,84 +889,102 @@ namespace mbgl {
- (void)setIconColor:(MGLStyleValue<MGLColor *> *)iconColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(iconColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(iconColor);
self.rawLayer->setIconColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)iconColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconColor() ?: self.rawLayer->getDefaultIconColor();
+ auto propertyValue = self.rawLayer->getIconColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultIconColor());
+ }
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setIconHaloBlur:(MGLStyleValue<NSNumber *> *)iconHaloBlur {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconHaloBlur);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconHaloBlur);
self.rawLayer->setIconHaloBlur(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconHaloBlur {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconHaloBlur() ?: self.rawLayer->getDefaultIconHaloBlur();
+ auto propertyValue = self.rawLayer->getIconHaloBlur();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconHaloBlur());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconHaloColor:(MGLStyleValue<MGLColor *> *)iconHaloColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(iconHaloColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(iconHaloColor);
self.rawLayer->setIconHaloColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)iconHaloColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconHaloColor() ?: self.rawLayer->getDefaultIconHaloColor();
+ auto propertyValue = self.rawLayer->getIconHaloColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultIconHaloColor());
+ }
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setIconHaloWidth:(MGLStyleValue<NSNumber *> *)iconHaloWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconHaloWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconHaloWidth);
self.rawLayer->setIconHaloWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconHaloWidth {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconHaloWidth() ?: self.rawLayer->getDefaultIconHaloWidth();
+ auto propertyValue = self.rawLayer->getIconHaloWidth();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconHaloWidth());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconOpacity:(MGLStyleValue<NSNumber *> *)iconOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconOpacity);
self.rawLayer->setIconOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconOpacity() ?: self.rawLayer->getDefaultIconOpacity();
+ auto propertyValue = self.rawLayer->getIconOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconOpacity());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconTranslation:(MGLStyleValue<NSValue *> *)iconTranslation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(iconTranslation);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(iconTranslation);
self.rawLayer->setIconTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconTranslation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconTranslate() ?: self.rawLayer->getDefaultIconTranslate();
+ auto propertyValue = self.rawLayer->getIconTranslate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultIconTranslate());
+ }
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
@@ -883,7 +1005,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)iconTranslationAnchor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getIconTranslateAnchor() ?: self.rawLayer->getDefaultIconTranslateAnchor();
+ auto propertyValue = self.rawLayer->getIconTranslateAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLIconTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultIconTranslateAnchor());
+ }
return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLIconTranslationAnchor>().toEnumStyleValue(propertyValue);
}
@@ -897,84 +1022,102 @@ namespace mbgl {
- (void)setTextColor:(MGLStyleValue<MGLColor *> *)textColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(textColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(textColor);
self.rawLayer->setTextColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)textColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextColor() ?: self.rawLayer->getDefaultTextColor();
+ auto propertyValue = self.rawLayer->getTextColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultTextColor());
+ }
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setTextHaloBlur:(MGLStyleValue<NSNumber *> *)textHaloBlur {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textHaloBlur);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textHaloBlur);
self.rawLayer->setTextHaloBlur(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textHaloBlur {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextHaloBlur() ?: self.rawLayer->getDefaultTextHaloBlur();
+ auto propertyValue = self.rawLayer->getTextHaloBlur();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextHaloBlur());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextHaloColor:(MGLStyleValue<MGLColor *> *)textHaloColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(textHaloColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(textHaloColor);
self.rawLayer->setTextHaloColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)textHaloColor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextHaloColor() ?: self.rawLayer->getDefaultTextHaloColor();
+ auto propertyValue = self.rawLayer->getTextHaloColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultTextHaloColor());
+ }
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setTextHaloWidth:(MGLStyleValue<NSNumber *> *)textHaloWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textHaloWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textHaloWidth);
self.rawLayer->setTextHaloWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textHaloWidth {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextHaloWidth() ?: self.rawLayer->getDefaultTextHaloWidth();
+ auto propertyValue = self.rawLayer->getTextHaloWidth();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextHaloWidth());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextOpacity:(MGLStyleValue<NSNumber *> *)textOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textOpacity);
self.rawLayer->setTextOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textOpacity {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextOpacity() ?: self.rawLayer->getDefaultTextOpacity();
+ auto propertyValue = self.rawLayer->getTextOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextOpacity());
+ }
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextTranslation:(MGLStyleValue<NSValue *> *)textTranslation {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(textTranslation);
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(textTranslation);
self.rawLayer->setTextTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)textTranslation {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextTranslate() ?: self.rawLayer->getDefaultTextTranslate();
+ auto propertyValue = self.rawLayer->getTextTranslate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultTextTranslate());
+ }
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
@@ -995,7 +1138,10 @@ namespace mbgl {
- (MGLStyleValue<NSValue *> *)textTranslationAnchor {
MGLAssertStyleLayerIsValid();
- auto propertyValue = self.rawLayer->getTextTranslateAnchor() ?: self.rawLayer->getDefaultTextTranslateAnchor();
+ auto propertyValue = self.rawLayer->getTextTranslateAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLTextTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultTextTranslateAnchor());
+ }
return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLTextTranslationAnchor>().toEnumStyleValue(propertyValue);
}
diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.h b/platform/darwin/src/MGLTilePyramidOfflineRegion.h
index 4e9f394e74..31e5a41920 100644
--- a/platform/darwin/src/MGLTilePyramidOfflineRegion.h
+++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLOfflineRegion.h"
#import "MGLGeometry.h"
@@ -9,14 +10,15 @@ NS_ASSUME_NONNULL_BEGIN
An offline region defined by a style URL, geographic coordinate bounds, and
range of zoom levels.
*/
+MGL_EXPORT
@interface MGLTilePyramidOfflineRegion : NSObject <MGLOfflineRegion, NSSecureCoding, NSCopying>
/**
URL of the style whose resources are required for offline viewing.
-
+
In addition to the JSON stylesheet, different styles may require different font
glyphs, sprite sheets, and other resources.
-
+
The URL may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s
map ID (`mapbox://styles/{user}/{style}`).
*/
@@ -30,14 +32,14 @@ NS_ASSUME_NONNULL_BEGIN
/**
The minimum zoom level for which to download tiles and other resources.
-
+
For more information about zoom levels, `-[MGLMapView zoomLevel]`.
*/
@property (nonatomic, readonly) double minimumZoomLevel;
/**
The maximum zoom level for which to download tiles and other resources.
-
+
For more information about zoom levels, `-[MGLMapView zoomLevel]`.
*/
@property (nonatomic, readonly) double maximumZoomLevel;
@@ -47,9 +49,9 @@ NS_ASSUME_NONNULL_BEGIN
/**
Initializes a newly created offline region with the given style URL, geographic
coordinate bounds, and range of zoom levels.
-
+
This is the designated initializer for `MGLTilePyramidOfflineRegion`.
-
+
@param styleURL URL of the map style for which to download resources. The URL
may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s map
ID (`mapbox://styles/{user}/{style}`). Specify `nil` for the default style.
diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm
index f128fbb256..e0d56484bf 100644
--- a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm
+++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm
@@ -35,7 +35,7 @@
if (!styleURL) {
styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];
}
-
+
if (!styleURL.scheme) {
[NSException raise:@"Invalid style URL" format:
@"%@ does not support setting a relative file URL as the style URL. "
@@ -44,7 +44,7 @@
@"For Mapbox-hosted styles, use the mapbox: scheme.",
NSStringFromClass([self class])];
}
-
+
_styleURL = styleURL;
_bounds = bounds;
_minimumZoomLevel = minimumZoomLevel;
@@ -80,7 +80,7 @@
MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(sw, ne);
double minimumZoomLevel = [coder decodeDoubleForKey:@"minimumZoomLevel"];
double maximumZoomLevel = [coder decodeDoubleForKey:@"maximumZoomLevel"];
-
+
return [self initWithStyleURL:styleURL bounds:bounds fromZoomLevel:minimumZoomLevel toZoomLevel:maximumZoomLevel];
}
@@ -106,7 +106,7 @@
if (![other isKindOfClass:[self class]]) {
return NO;
}
-
+
MGLTilePyramidOfflineRegion *otherRegion = other;
return (_minimumZoomLevel == otherRegion->_minimumZoomLevel
&& _maximumZoomLevel == otherRegion->_maximumZoomLevel
diff --git a/platform/darwin/src/MGLTileSource.h b/platform/darwin/src/MGLTileSource.h
index db5bc73338..bc29b0f95c 100644
--- a/platform/darwin/src/MGLTileSource.h
+++ b/platform/darwin/src/MGLTileSource.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLSource.h"
#import "MGLTypes.h"
@@ -15,7 +16,7 @@ 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.
@@ -24,12 +25,12 @@ typedef NSString *MGLTileSourceOption NS_STRING_ENUM;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel;
+extern MGL_EXPORT 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.
@@ -38,14 +39,14 @@ extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
+extern MGL_EXPORT 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.
@@ -54,21 +55,21 @@ extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
+extern MGL_EXPORT 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;
+extern MGL_EXPORT 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.
@@ -77,30 +78,30 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
+extern MGL_EXPORT 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;
+extern MGL_EXPORT 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`.
This option corresponds to the `scheme` key in the
<a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">TileJSON</a>
specification.
*/
-extern const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem;
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem;
/**
Tile coordinate systems that determine how tile coordinates in tile URLs are
@@ -110,16 +111,16 @@ 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
<a href="http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification">Tile Map Service Specification</a>.
*/
@@ -134,11 +135,12 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
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`.
*/
+MGL_EXPORT
@interface MGLTileSource : MGLSource
#pragma mark Initializing a Source
@@ -148,15 +150,15 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
/**
Returns a tile source initialized with an identifier and configuration URL.
-
+
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
-
+
The URL may be a full HTTP or HTTPS URL or, for tile sets hosted by Mapbox, a
Mapbox URL indicating a map identifier (`mapbox://<mapid>`). The URL should
point to a JSON file that conforms to the
<a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>.
-
+
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param configurationURL A URL to a TileJSON configuration file describing the
@@ -168,27 +170,27 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
/**
Returns a tile source initialized an identifier, tile URL templates, and
options.
-
+
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
-
+
#### Tile URL templates
-
+
Tile URL templates are strings that specify the URLs of the tile images to
load. Each template resembles an absolute URL, but with any number of
placeholder strings that the source evaluates based on the tile it needs to
load. For example:
-
+
<ul>
<li><code>http://www.example.com/tiles/{z}/{x}/{y}.pbf</code> could be
evaluated as <code>http://www.example.com/tiles/14/6/9.pbf</code>.</li>
<li><code>http://www.example.com/tiles/{z}/{x}/{y}{ratio}.png</code> could be
evaluated as <code>http://www.example.com/tiles/14/6/9@2x.png</code>.</li>
</ul>
-
+
Tile sources support the following placeholder strings in tile URL templates,
all of which are optional:
-
+
<table>
<thead>
<tr><th>Placeholder string</th><th>Description</th></tr>
@@ -254,11 +256,11 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
</tr>
</tbody>
</table>
-
+
For more information about the `{x}`, `{y}`, and `{z}` placeholder strings,
consult the
<a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">OpenStreetMap Wiki</a>.
-
+
@param identifier A string that uniquely identifies the source in the style to
which it is added.
@param tileURLTemplates An array of tile URL template strings. Only the first
@@ -286,7 +288,7 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
/**
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.
diff --git a/platform/darwin/src/MGLTileSource.mm b/platform/darwin/src/MGLTileSource.mm
index 1aef81d53c..aa2a299a46 100644
--- a/platform/darwin/src/MGLTileSource.mm
+++ b/platform/darwin/src/MGLTileSource.mm
@@ -53,11 +53,11 @@ const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem = @"MGLTileSou
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]) {
@@ -78,7 +78,7 @@ mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTem
[NSException raise:NSInvalidArgumentException
format:@"MGLTileSourceOptionMinimumZoomLevel must be less than MGLTileSourceOptionMaximumZoomLevel."];
}
-
+
if (NSString *attribution = options[MGLTileSourceOptionAttributionHTMLString]) {
if (![attribution isKindOfClass:[NSString class]]) {
[NSException raise:NSInvalidArgumentException
@@ -86,13 +86,13 @@ mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTem
}
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";
@@ -107,7 +107,7 @@ mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTem
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
@@ -124,6 +124,6 @@ mbgl::Tileset MGLTileSetFromTileURLTemplates(NS_ARRAY_OF(NSString *) *tileURLTem
break;
}
}
-
+
return tileSet;
}
diff --git a/platform/darwin/src/MGLTileSource_Private.h b/platform/darwin/src/MGLTileSource_Private.h
index ca80e3d960..0d9876d412 100644
--- a/platform/darwin/src/MGLTileSource_Private.h
+++ b/platform/darwin/src/MGLTileSource_Private.h
@@ -1,7 +1,8 @@
-#import "MGLTileSource.h"
-
#import <CoreGraphics/CoreGraphics.h>
+#import "MGLFoundation.h"
+#import "MGLTileSource.h"
+
NS_ASSUME_NONNULL_BEGIN
namespace mbgl {
@@ -14,7 +15,7 @@ namespace mbgl {
/**
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.
*/
@@ -23,7 +24,7 @@ namespace mbgl {
/**
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.
*/
@@ -31,6 +32,7 @@ namespace mbgl {
@end
+MGL_EXPORT
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/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index a6b7254b58..8cd2cacaa6 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -1,5 +1,7 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
+
#pragma once
#if TARGET_OS_IPHONE
@@ -28,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
#endif
/** Indicates an error occurred in the Mapbox SDK. */
-extern NSErrorDomain const MGLErrorDomain;
+extern MGL_EXPORT NSErrorDomain const MGLErrorDomain;
/** Error constants for the Mapbox SDK. */
typedef NS_ENUM(NSInteger, MGLErrorCode) {
diff --git a/platform/darwin/src/MGLValueEvaluator.h b/platform/darwin/src/MGLValueEvaluator.h
index b53cdaa8d2..2779deba90 100644
--- a/platform/darwin/src/MGLValueEvaluator.h
+++ b/platform/darwin/src/MGLValueEvaluator.h
@@ -10,27 +10,27 @@ public:
id operator()(const mbgl::NullValue &) const {
return [NSNull null];
}
-
+
id operator()(const bool &value) const {
return value ? @YES : @NO;
}
-
+
id operator()(const uint64_t &value) const {
return @(value);
}
-
+
id operator()(const int64_t &value) const {
return @(value);
}
-
+
id operator()(const double &value) const {
return @(value);
}
-
+
id operator()(const std::string &value) const {
return @(value.c_str());
}
-
+
id operator()(const std::vector<mbgl::Value> &values) const {
NSMutableArray *objects = [NSMutableArray arrayWithCapacity:values.size()];
for (const auto &v : values) {
@@ -38,7 +38,7 @@ public:
}
return objects;
}
-
+
id operator()(const std::unordered_map<std::string, mbgl::Value> &items) const {
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:items.size()];
for (auto &item : items) {
diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h
index 5032ca3863..2322c62f29 100644
--- a/platform/darwin/src/MGLVectorSource.h
+++ b/platform/darwin/src/MGLVectorSource.h
@@ -1,3 +1,4 @@
+#import "MGLFoundation.h"
#import "MGLTileSource.h"
NS_ASSUME_NONNULL_BEGIN
@@ -11,22 +12,22 @@ NS_ASSUME_NONNULL_BEGIN
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.
-
+
Each
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-vector"><code>vector</code></a>
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&nbsp;×&nbsp;<var>extent</var> and
(<var>extent</var>&nbsp;×&nbsp;2)&nbsp;−&nbsp;1, inclusive. Any vector style
layer initialized with a vector source must have a non-`nil` value in its
`sourceLayerIdentifier` property.
-
+
### Example
-
+
```swift
let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
.minimumZoomLevel: 9,
@@ -38,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
mapView.style?.addSource(source)
```
*/
+MGL_EXPORT
@interface MGLVectorSource : MGLTileSource
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL NS_DESIGNATED_INITIALIZER;
diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm
index c95ff63bbf..a16cfa6d81 100644
--- a/platform/darwin/src/MGLVectorSource.mm
+++ b/platform/darwin/src/MGLVectorSource.mm
@@ -5,7 +5,7 @@
#import "MGLTileSource_Private.h"
#import "NSURL+MGLAdditions.h"
-#include <mbgl/mbgl.hpp>
+#include <mbgl/map/map.hpp>
#include <mbgl/style/sources/vector_source.hpp>
@interface MGLVectorSource ()
@@ -33,7 +33,7 @@
- (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options {
if (self = [super initWithIdentifier:identifier tileURLTemplates:tileURLTemplates options:options]) {
mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options);
-
+
auto source = std::make_unique<mbgl::style::VectorSource>(identifier.UTF8String, tileSet);
_pendingSource = std::move(source);
self.rawSource = _pendingSource.get();
diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h
index 360b86c517..c6193e6046 100644
--- a/platform/darwin/src/MGLVectorStyleLayer.h
+++ b/platform/darwin/src/MGLVectorStyleLayer.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
+#import "MGLFoundation.h"
#import "MGLForegroundStyleLayer.h"
NS_ASSUME_NONNULL_BEGIN
@@ -7,12 +8,13 @@ NS_ASSUME_NONNULL_BEGIN
/**
`MGLVectorStyleLayer` is an abstract superclass for style layers whose content
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
subclasses: `MGLCircleStyleLayer`, `MGLFillStyleLayer`, `MGLLineStyleLayer`,
and `MGLSymbolStyleLayer`.
*/
+MGL_EXPORT
@interface MGLVectorStyleLayer : MGLForegroundStyleLayer
#pragma mark Refining a Style Layer’s Content
@@ -25,15 +27,15 @@ NS_ASSUME_NONNULL_BEGIN
/**
The style layer’s predicate.
-
+
Use the style layer’s predicate to include only the features in the source
layer that satisfy a condition that you define. If the style layer initially
comes from the style, its predicate corresponds to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#layer-filter">`filter`</a>
property in the style JSON.
-
+
The following comparison operators are supported.
-
+
<ul>
<li><code>NSEqualToPredicateOperatorType</code> (<code>=</code>, <code>==</code>)</li>
<li><code>NSGreaterThanOrEqualToPredicateOperatorType</code> (<code>>=</code>, <code>=></code>)</li>
@@ -43,35 +45,35 @@ NS_ASSUME_NONNULL_BEGIN
<li><code>NSNotEqualToPredicateOperatorType</code> (<code>!=</code>, <code><></code>)</li>
<li><code>NSBetweenPredicateOperatorType</code> (<code>BETWEEN</code>)</li>
</ul>
-
+
The following compound operators are supported:
-
+
<ul>
<li><code>NSAndPredicateType</code> (<code>AND</code>, <code>&&</code>)</li>
<li><code>NSOrPredicateType</code> (<code>OR</code>, <code>||</code>)</li>
<li><code>NSNotPredicateType</code> (<code>NOT</code>, <code>!</code>)</li>
</ul>
-
+
The following aggregate operators are supported:
-
+
<ul>
<li><code>NSInPredicateOperatorType</code> (<code>IN</code>)</li>
<li><code>NSContainsPredicateOperatorType</code> (<code>CONTAINS</code>)</li>
</ul>
-
+
To test whether a feature has or lacks a specific attribute, compare the
attribute to `NULL` or `NIL`. Predicates created using the
`+[NSPredicate predicateWithValue:]` method are also supported. String
operators and custom operators are not supported.
-
+
For details about the predicate format string syntax, consult the “Predicate
Format String Syntax” chapter of the
“<a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/">Predicate Programming Guide</a>”
in Apple developer documentation.
-
+
The predicate's left-hand expression must be a string that identifies a feature
attribute or, alternatively, one of the following special attributes:
-
+
<table>
<thead>
<tr><th>Attribute</th><th>Meaning</th></tr>
@@ -113,33 +115,33 @@ NS_ASSUME_NONNULL_BEGIN
</tr>
</tbody>
</table>
-
+
The predicate’s right-hand expression must be an `NSString` (to match strings)
or `NSNumber` (to match numbers, including Boolean values) or an array of
`NSString`s or `NSNumber`s, depending on the operator and the type of values
expected for the attribute being tested. For floating-point values, use
`-[NSNumber numberWithDouble:]` instead of `-[NSNumber numberWithFloat:]`
to avoid precision issues.
-
+
Automatic type casting is not performed. Therefore, a feature only matches this
predicate if its value for the attribute in question is of the same type as the
value specified in the predicate. Also, operator modifiers such as `c` (for
case insensitivity), `d` (for diacritic insensitivity), and `l` (for locale
sensitivity) 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
+
+ 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"`.
-
+
### Example
-
+
To filter the layer to include only the features whose `index` attribute is 5
or 10 and whose `ele` attribute is at least 1,500, you could create an
`NSCompoundPredicate` along these lines:
-
+
```swift
let layer = MGLLineStyleLayer(identifier: "contour", source: terrain)
layer.sourceLayerIdentifier = "contours"
diff --git a/platform/darwin/src/NSArray+MGLAdditions.mm b/platform/darwin/src/NSArray+MGLAdditions.mm
index 8ec344f580..3cab7ff427 100644
--- a/platform/darwin/src/NSArray+MGLAdditions.mm
+++ b/platform/darwin/src/NSArray+MGLAdditions.mm
@@ -50,15 +50,15 @@
- (std::vector<CLLocationCoordinate2D>)mgl_coordinates {
NSUInteger numberOfCoordinates = [self count];
CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(numberOfCoordinates * sizeof(CLLocationCoordinate2D));
-
+
for (NSUInteger i = 0; i < numberOfCoordinates; i++) {
coords[i] = CLLocationCoordinate2DMake([self[i][@"latitude"] doubleValue],
[self[i][@"longitude"] doubleValue]);
}
-
+
std::vector<CLLocationCoordinate2D> coordinates = { coords, coords + numberOfCoordinates };
free(coords);
-
+
return coordinates;
}
diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
index 58b37fae0e..ac2d598d05 100644
--- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
@@ -5,8 +5,7 @@
@implementation NSComparisonPredicate (MGLAdditions)
-- (mbgl::style::Filter)mgl_filter
-{
+- (mbgl::style::Filter)mgl_filter {
NSExpression *leftExpression = self.leftExpression;
NSExpression *rightExpression = self.rightExpression;
NSExpressionType leftType = leftExpression.expressionType;
@@ -19,13 +18,32 @@
eqFilter.key = self.mgl_keyPath.UTF8String;
eqFilter.value = self.mgl_constantValue;
+ // Convert $type == to TypeEqualsFilter.
+ if (eqFilter.key == "$type") {
+ mbgl::style::TypeEqualsFilter typeEqFilter;
+ typeEqFilter.value = self.mgl_featureType;
+ return typeEqFilter;
+ }
+
+ // Convert $id == to IdentifierEqualsFilter.
+ if (eqFilter.key == "$id") {
+ // Convert $id == nil to NotHasIdentifierFilter.
+ if (eqFilter.value.is<mbgl::NullValue>()) {
+ return mbgl::style::NotHasIdentifierFilter();
+ }
+
+ mbgl::style::IdentifierEqualsFilter idEqFilter;
+ idEqFilter.value = self.mgl_featureIdentifier;
+ return idEqFilter;
+ }
+
// Convert == nil to NotHasFilter.
if (eqFilter.value.is<mbgl::NullValue>()) {
mbgl::style::NotHasFilter notHasFilter;
notHasFilter.key = eqFilter.key;
return notHasFilter;
}
-
+
return eqFilter;
}
case NSNotEqualToPredicateOperatorType: {
@@ -33,13 +51,32 @@
neFilter.key = self.mgl_keyPath.UTF8String;
neFilter.value = self.mgl_constantValue;
+ // Convert $type != to TypeNotEqualsFilter.
+ if (neFilter.key == "$type") {
+ mbgl::style::TypeNotEqualsFilter typeNeFilter;
+ typeNeFilter.value = self.mgl_featureType;
+ return typeNeFilter;
+ }
+
+ // Convert $id != to IdentifierNotEqualsFilter.
+ if (neFilter.key == "$id") {
+ // Convert $id != nil to HasIdentifierFilter.
+ if (neFilter.value.is<mbgl::NullValue>()) {
+ return mbgl::style::HasIdentifierFilter();
+ }
+
+ mbgl::style::IdentifierNotEqualsFilter idNeFilter;
+ idNeFilter.value = self.mgl_featureIdentifier;
+ return idNeFilter;
+ }
+
// Convert != nil to HasFilter.
if (neFilter.value.is<mbgl::NullValue>()) {
mbgl::style::HasFilter hasFilter;
hasFilter.key = neFilter.key;
return hasFilter;
}
-
+
return neFilter;
}
case NSGreaterThanPredicateOperatorType: {
@@ -103,6 +140,21 @@
[NSException raise:NSInvalidArgumentException
format:@"Predicate cannot compare values IN attribute."];
}
+
+ // Convert $type IN to TypeInFilter.
+ if ([leftExpression.keyPath isEqualToString:@"$type"]) {
+ mbgl::style::TypeInFilter typeInFilter;
+ typeInFilter.values = rightExpression.mgl_aggregateFeatureType;
+ return typeInFilter;
+ }
+
+ // Convert $id IN to IdentifierInFilter.
+ if ([leftExpression.keyPath isEqualToString:@"$id"]) {
+ mbgl::style::IdentifierInFilter idInFilter;
+ idInFilter.values = rightExpression.mgl_aggregateFeatureIdentifier;
+ return idInFilter;
+ }
+
mbgl::style::InFilter inFilter;
inFilter.key = leftExpression.keyPath.UTF8String;
inFilter.values = rightExpression.mgl_aggregateMBGLValue;
@@ -117,6 +169,21 @@
[NSException raise:NSInvalidArgumentException
format:@"Predicate cannot compare attribute CONTAINS values."];
}
+
+ // Convert CONTAINS $type to TypeInFilter.
+ if ([rightExpression.keyPath isEqualToString:@"$type"]) {
+ mbgl::style::TypeInFilter typeInFilter;
+ typeInFilter.values = leftExpression.mgl_aggregateFeatureType;
+ return typeInFilter;
+ }
+
+ // Convert CONTAINS $id to IdentifierInFilter.
+ if ([rightExpression.keyPath isEqualToString:@"$id"]) {
+ mbgl::style::IdentifierInFilter idInFilter;
+ idInFilter.values = leftExpression.mgl_aggregateFeatureIdentifier;
+ return idInFilter;
+ }
+
mbgl::style::InFilter inFilter;
inFilter.key = rightExpression.keyPath.UTF8String;
inFilter.values = leftExpression.mgl_aggregateMBGLValue;
@@ -155,7 +222,7 @@
[NSException raise:NSInvalidArgumentException
format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType];
}
-
+
return {};
}
@@ -169,7 +236,7 @@
} else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
return rightExpression.keyPath;
}
-
+
[NSException raise:NSInvalidArgumentException
format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
return nil;
@@ -192,4 +259,38 @@
return value;
}
+- (mbgl::FeatureType)mgl_featureType {
+ NSExpression *leftExpression = self.leftExpression;
+ NSExpression *rightExpression = self.rightExpression;
+ NSExpressionType leftType = leftExpression.expressionType;
+ NSExpressionType rightType = rightExpression.expressionType;
+ mbgl::FeatureType type;
+ if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) {
+ type = rightExpression.mgl_featureType;
+ } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
+ type = leftExpression.mgl_featureType;
+ } else {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
+ }
+ return type;
+}
+
+- (mbgl::FeatureIdentifier)mgl_featureIdentifier {
+ NSExpression *leftExpression = self.leftExpression;
+ NSExpression *rightExpression = self.rightExpression;
+ NSExpressionType leftType = leftExpression.expressionType;
+ NSExpressionType rightType = rightExpression.expressionType;
+ mbgl::FeatureIdentifier identifier;
+ if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) {
+ identifier = rightExpression.mgl_featureIdentifier;
+ } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
+ identifier = leftExpression.mgl_featureIdentifier;
+ } else {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
+ }
+ return identifier;
+}
+
@end
diff --git a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm
index 2697467198..0039b5af82 100644
--- a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm
@@ -21,19 +21,19 @@
NSAssert(self.subpredicates.count <= 1, @"NOT predicate cannot have multiple subpredicates.");
NSPredicate *subpredicate = self.subpredicates.firstObject;
mbgl::style::Filter subfilter = subpredicate.mgl_filter;
-
+
// Convert NOT(!= nil) to NotHasFilter.
if (subfilter.is<mbgl::style::HasFilter>()) {
auto hasFilter = subfilter.get<mbgl::style::HasFilter>();
return mbgl::style::NotHasFilter { .key = hasFilter.key };
}
-
+
// Convert NOT(== nil) to HasFilter.
if (subfilter.is<mbgl::style::NotHasFilter>()) {
auto hasFilter = subfilter.get<mbgl::style::NotHasFilter>();
return mbgl::style::HasFilter { .key = hasFilter.key };
}
-
+
// Convert NOT(IN) or NOT(CONTAINS) to NotInFilter.
if (subfilter.is<mbgl::style::InFilter>()) {
auto inFilter = subfilter.get<mbgl::style::InFilter>();
@@ -42,7 +42,7 @@
notInFilter.values = inFilter.values;
return notInFilter;
}
-
+
// Convert NOT(), NOT(AND), NOT(NOT), NOT(==), etc. into NoneFilter.
mbgl::style::NoneFilter noneFilter;
if (subfilter.is<mbgl::style::AnyFilter>()) {
@@ -64,7 +64,7 @@
return filter;
}
}
-
+
[NSException raise:@"Compound predicate type not handled"
format:@""];
return {};
diff --git a/platform/darwin/src/NSData+MGLAdditions.mm b/platform/darwin/src/NSData+MGLAdditions.mm
index ef171c5e1e..97c3bb4a26 100644
--- a/platform/darwin/src/NSData+MGLAdditions.mm
+++ b/platform/darwin/src/NSData+MGLAdditions.mm
@@ -8,7 +8,7 @@
{
std::string string(static_cast<const char*>(self.bytes), self.length);
std::string compressed_string = mbgl::util::compress(string);
-
+
return [NSData dataWithBytes:&compressed_string[0] length:compressed_string.length()];
}
@@ -16,7 +16,7 @@
{
std::string string(static_cast<const char*>(self.bytes), self.length);
std::string decompressed_string = mbgl::util::decompress(string);
-
+
return [NSData dataWithBytes:&decompressed_string[0] length:decompressed_string.length()];
}
diff --git a/platform/darwin/src/NSDate+MGLAdditions.h b/platform/darwin/src/NSDate+MGLAdditions.h
index a116ef32de..820d1bd9e2 100644
--- a/platform/darwin/src/NSDate+MGLAdditions.h
+++ b/platform/darwin/src/NSDate+MGLAdditions.h
@@ -1,11 +1,13 @@
#import <Foundation/Foundation.h>
-#include <mbgl/mbgl.hpp>
#include <mbgl/util/chrono.hpp>
@interface NSDate (MGLAdditions)
/// Converts from a duration in seconds to a duration object usable in mbgl.
-mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration);
+mbgl::Duration MGLDurationInSecondsFromTimeInterval(NSTimeInterval duration);
+
+/// Converts from an mbgl duration object to a duration in seconds.
+NSTimeInterval MGLTimeIntervalFromDurationInSeconds(mbgl::Duration duration);
@end
diff --git a/platform/darwin/src/NSDate+MGLAdditions.mm b/platform/darwin/src/NSDate+MGLAdditions.mm
index 75072ad7ff..deac3c4881 100644
--- a/platform/darwin/src/NSDate+MGLAdditions.mm
+++ b/platform/darwin/src/NSDate+MGLAdditions.mm
@@ -2,9 +2,14 @@
@implementation NSDate (MGLAdditions)
-mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
+mbgl::Duration MGLDurationInSecondsFromTimeInterval(NSTimeInterval duration)
{
return std::chrono::duration_cast<mbgl::Duration>(std::chrono::duration<NSTimeInterval>(duration));
}
+NSTimeInterval MGLTimeIntervalFromDurationInSeconds(mbgl::Duration duration)
+{
+ return duration.count();
+}
+
@end
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h
index c60d6d78ba..491ed5a536 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLAdditions.h
@@ -8,7 +8,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) mbgl::Value mgl_constantMBGLValue;
@property (nonatomic, readonly) std::vector<mbgl::Value> mgl_aggregateMBGLValue;
+@property (nonatomic, readonly) mbgl::FeatureType mgl_featureType;
+@property (nonatomic, readonly) std::vector<mbgl::FeatureType> mgl_aggregateFeatureType;
@property (nonatomic, readonly) mbgl::FeatureIdentifier mgl_featureIdentifier;
+@property (nonatomic, readonly) std::vector<mbgl::FeatureIdentifier> mgl_aggregateFeatureIdentifier;
@end
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index f11a1919cf..a7759cda9d 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -1,5 +1,12 @@
#import "NSExpression+MGLAdditions.h"
+#import "MGLTypes.h"
+#if TARGET_OS_IPHONE
+ #import "UIColor+MGLAdditions.h"
+#else
+ #import "NSColor+MGLAdditions.h"
+#endif
+
@implementation NSExpression (MGLAdditions)
- (std::vector<mbgl::Value>)mgl_aggregateMBGLValue {
@@ -56,6 +63,9 @@
// We use long long here to avoid any truncation.
return { (int64_t)number.longLongValue };
}
+ } else if ([value isKindOfClass:[MGLColor class]]) {
+ auto hexString = [(MGLColor *)value mgl_color].stringify();
+ return { hexString };
} else if (value && value != [NSNull null]) {
[NSException raise:NSInvalidArgumentException
format:@"Can’t convert %s:%@ to mbgl::Value", [value objCType], value];
@@ -63,15 +73,73 @@
return {};
}
+- (std::vector<mbgl::FeatureType>)mgl_aggregateFeatureType {
+ if ([self.constantValue isKindOfClass:[NSArray class]] || [self.constantValue isKindOfClass:[NSSet class]]) {
+ std::vector<mbgl::FeatureType> convertedValues;
+ for (id value in self.constantValue) {
+ NSExpression *expression = value;
+ if (![expression isKindOfClass:[NSExpression class]]) {
+ expression = [NSExpression expressionForConstantValue:expression];
+ }
+ convertedValues.push_back(expression.mgl_featureType);
+ }
+ return convertedValues;
+ }
+ [NSException raise:NSInvalidArgumentException
+ format:@"Constant value expression must contain an array or set."];
+ return {};
+}
+
+- (mbgl::FeatureType)mgl_featureType {
+ id value = self.constantValue;
+ if ([value isKindOfClass:NSString.class]) {
+ if ([value isEqualToString:@"Point"]) {
+ return mbgl::FeatureType::Point;
+ }
+ if ([value isEqualToString:@"LineString"]) {
+ return mbgl::FeatureType::LineString;
+ }
+ if ([value isEqualToString:@"Polygon"]) {
+ return mbgl::FeatureType::Polygon;
+ }
+ } else if ([value isKindOfClass:NSNumber.class]) {
+ switch ([value integerValue]) {
+ case 1:
+ return mbgl::FeatureType::Point;
+ case 2:
+ return mbgl::FeatureType::LineString;
+ case 3:
+ return mbgl::FeatureType::Polygon;
+ default:
+ break;
+ }
+ }
+ return mbgl::FeatureType::Unknown;
+}
+
+- (std::vector<mbgl::FeatureIdentifier>)mgl_aggregateFeatureIdentifier {
+ if ([self.constantValue isKindOfClass:[NSArray class]] || [self.constantValue isKindOfClass:[NSSet class]]) {
+ std::vector<mbgl::FeatureIdentifier> convertedValues;
+ for (id value in self.constantValue) {
+ NSExpression *expression = value;
+ if (![expression isKindOfClass:[NSExpression class]]) {
+ expression = [NSExpression expressionForConstantValue:expression];
+ }
+ convertedValues.push_back(expression.mgl_featureIdentifier);
+ }
+ return convertedValues;
+ }
+ [NSException raise:NSInvalidArgumentException
+ format:@"Constant value expression must contain an array or set."];
+ return {};
+}
+
- (mbgl::FeatureIdentifier)mgl_featureIdentifier {
mbgl::Value mbglValue = self.mgl_constantMBGLValue;
-
+
if (mbglValue.is<std::string>()) {
return mbglValue.get<std::string>();
}
- if (mbglValue.is<bool>()) {
- return mbglValue.get<bool>();
- }
if (mbglValue.is<double>()) {
return mbglValue.get<double>();
}
@@ -81,7 +149,7 @@
if (mbglValue.is<int64_t>()) {
return mbglValue.get<int64_t>();
}
-
+
return {};
}
diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm
index 0ac68095f9..e0511d8740 100644
--- a/platform/darwin/src/NSPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm
@@ -4,7 +4,7 @@
class FilterEvaluator {
public:
-
+
NSArray *getPredicates(std::vector<mbgl::style::Filter> filters) {
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:filters.size()];
for (auto filter : filters) {
@@ -12,52 +12,111 @@ public:
}
return predicates;
}
-
- NSExpression *getValues(std::vector<mbgl::Value> values) {
+
+ template <typename MBGLType>
+ NSExpression *getValues(std::vector<MBGLType> values) {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()];
for (auto value : values) {
- id constantValue = mbgl::Value::visit(value, ValueEvaluator());
+ id constantValue = MBGLType::visit(value, ValueEvaluator());
[array addObject:[NSExpression expressionForConstantValue:constantValue]];
}
return [NSExpression expressionForAggregate:array];
}
+ NSString *getFeatureTypeString(mbgl::FeatureType type) {
+ switch (type) {
+ case mbgl::FeatureType::Point:
+ return @"Point";
+
+ case mbgl::FeatureType::LineString:
+ return @"LineString";
+
+ case mbgl::FeatureType::Polygon:
+ return @"Polygon";
+
+ default:
+ NSCAssert(NO, @"Unrecognized feature type %hhu", type);
+ return nil;
+ }
+ }
+
+ NSExpression *getFeatureTypeStrings(std::vector<mbgl::FeatureType> values) {
+ NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()];
+ for (auto value : values) {
+ id typeString = getFeatureTypeString(value);
+ [array addObject:[NSExpression expressionForConstantValue:typeString]];
+ }
+ return [NSExpression expressionForAggregate:array];
+ }
+
NSPredicate *operator()(mbgl::style::NullFilter filter) {
return nil;
}
-
+
NSPredicate *operator()(mbgl::style::EqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K == %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())];
}
-
+
NSPredicate *operator()(mbgl::style::NotEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K != %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())];
}
-
+
NSPredicate *operator()(mbgl::style::GreaterThanFilter filter) {
return [NSPredicate predicateWithFormat:@"%K > %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())];
}
-
+
NSPredicate *operator()(mbgl::style::GreaterThanEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K >= %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())];
}
-
+
NSPredicate *operator()(mbgl::style::LessThanFilter filter) {
return [NSPredicate predicateWithFormat:@"%K < %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())];
}
-
+
NSPredicate *operator()(mbgl::style::LessThanEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K <= %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())];
}
-
+
NSPredicate *operator()(mbgl::style::InFilter filter) {
return [NSPredicate predicateWithFormat:@"%K IN %@", @(filter.key.c_str()), getValues(filter.values)];
}
-
+
NSPredicate *operator()(mbgl::style::NotInFilter filter) {
return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @(filter.key.c_str()), getValues(filter.values)];
}
+ NSPredicate *operator()(mbgl::style::TypeEqualsFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K == %@", @"$type", getFeatureTypeString(filter.value)];
+ }
+
+ NSPredicate *operator()(mbgl::style::TypeNotEqualsFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K != %@", @"$type", getFeatureTypeString(filter.value)];
+ }
+
+ NSPredicate *operator()(mbgl::style::TypeInFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K IN %@", @"$type", getFeatureTypeStrings(filter.values)];
+ }
+
+ NSPredicate *operator()(mbgl::style::TypeNotInFilter filter) {
+ return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @"$type", getFeatureTypeStrings(filter.values)];
+ }
+
+ NSPredicate *operator()(mbgl::style::IdentifierEqualsFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K == %@", @"$id", mbgl::FeatureIdentifier::visit(filter.value, ValueEvaluator())];
+ }
+
+ NSPredicate *operator()(mbgl::style::IdentifierNotEqualsFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K != %@", @"$id", mbgl::FeatureIdentifier::visit(filter.value, ValueEvaluator())];
+ }
+
+ NSPredicate *operator()(mbgl::style::IdentifierInFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K IN %@", @"$id", getValues(filter.values)];
+ }
+
+ NSPredicate *operator()(mbgl::style::IdentifierNotInFilter filter) {
+ return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @"$id", getValues(filter.values)];
+ }
+
NSPredicate *operator()(mbgl::style::AnyFilter filter) {
NSArray *subpredicates = getPredicates(filter.filters);
if (subpredicates.count) {
@@ -65,13 +124,13 @@ public:
}
return [NSPredicate predicateWithValue:NO];
}
-
+
NSPredicate *operator()(mbgl::style::AllFilter filter) {
// Convert [all, [>=, key, lower], [<=, key, upper]] to key BETWEEN {lower, upper}
if (filter.filters.size() == 2) {
auto leftFilter = filter.filters[0];
auto rightFilter = filter.filters[1];
-
+
std::string lowerKey;
std::string upperKey;
mbgl::Value lowerBound;
@@ -83,7 +142,7 @@ public:
lowerKey = rightFilter.get<mbgl::style::GreaterThanEqualsFilter>().key;
lowerBound = rightFilter.get<mbgl::style::GreaterThanEqualsFilter>().value;
}
-
+
if (leftFilter.is<mbgl::style::LessThanEqualsFilter>()) {
upperKey = leftFilter.get<mbgl::style::LessThanEqualsFilter>().key;
upperBound = leftFilter.get<mbgl::style::LessThanEqualsFilter>().value;
@@ -91,7 +150,7 @@ public:
upperKey = rightFilter.get<mbgl::style::LessThanEqualsFilter>().key;
upperBound = rightFilter.get<mbgl::style::LessThanEqualsFilter>().value;
}
-
+
if (!lowerBound.is<mbgl::NullValue>() && !upperBound.is<mbgl::NullValue>()
&& lowerKey == upperKey) {
return [NSPredicate predicateWithFormat:@"%K BETWEEN {%@, %@}",
@@ -100,14 +159,14 @@ public:
mbgl::Value::visit(upperBound, ValueEvaluator())];
}
}
-
+
NSArray *subpredicates = getPredicates(filter.filters);
if (subpredicates.count) {
return [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
}
return [NSPredicate predicateWithValue:YES];
}
-
+
NSPredicate *operator()(mbgl::style::NoneFilter filter) {
NSArray *subpredicates = getPredicates(filter.filters);
if (subpredicates.count > 1) {
@@ -119,15 +178,22 @@ public:
return [NSPredicate predicateWithValue:YES];
}
}
-
+
NSPredicate *operator()(mbgl::style::HasFilter filter) {
return [NSPredicate predicateWithFormat:@"%K != nil", @(filter.key.c_str())];
}
-
+
NSPredicate *operator()(mbgl::style::NotHasFilter filter) {
return [NSPredicate predicateWithFormat:@"%K == nil", @(filter.key.c_str())];
}
+ NSPredicate *operator()(mbgl::style::HasIdentifierFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K != nil", @"$id"];
+ }
+
+ NSPredicate *operator()(mbgl::style::NotHasIdentifierFilter filter) {
+ return [NSPredicate predicateWithFormat:@"%K == nil", @"$id"];
+ }
};
@implementation NSPredicate (MGLAdditions)
@@ -138,18 +204,18 @@ public:
{
return mbgl::style::AllFilter();
}
-
+
if ([self isEqual:[NSPredicate predicateWithValue:NO]])
{
return mbgl::style::AnyFilter();
}
-
+
if ([self.predicateFormat hasPrefix:@"BLOCKPREDICATE("])
{
[NSException raise:NSInvalidArgumentException
format:@"Block-based predicates are not supported."];
}
-
+
[NSException raise:NSInvalidArgumentException
format:@"Unrecognized predicate type."];
return {};
diff --git a/platform/darwin/src/NSString+MGLAdditions.h b/platform/darwin/src/NSString+MGLAdditions.h
index 246dc084f4..ff72e9d3af 100644
--- a/platform/darwin/src/NSString+MGLAdditions.h
+++ b/platform/darwin/src/NSString+MGLAdditions.h
@@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns a title-cased representation of the receiver using the specified
locale.
-
+
@param The locale. For strings presented to users, pass in the current locale
(`+[NSLocale currentLocale]`). To use the system locale, pass in `nil`.
*/
diff --git a/platform/darwin/src/NSString+MGLAdditions.m b/platform/darwin/src/NSString+MGLAdditions.m
index 5c32f4b789..371ef4023e 100644
--- a/platform/darwin/src/NSString+MGLAdditions.m
+++ b/platform/darwin/src/NSString+MGLAdditions.m
@@ -45,7 +45,7 @@
scanner.charactersToBeSkipped = nil;
NSString *prefix;
[scanner scanCharactersFromSet:set intoString:&prefix];
-
+
NSString *trimmedString = [self.string stringByTrimmingCharactersInSet:set];
return [self attributedSubstringFromRange:NSMakeRange(prefix.length, trimmedString.length)];
}
diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h
index 4a97c8e115..76388cf2bb 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.h
+++ b/platform/darwin/src/NSValue+MGLAdditions.h
@@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates a new value object containing the specified Core Location geographic
coordinate structure.
-
+
@param coordinate The value for the new object.
@return A new value object that contains the geographic coordinate information.
*/
@@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates a new value object containing the specified Mapbox coordinate span
structure.
-
+
@param span The value for the new object.
@return A new value object that contains the coordinate span information.
*/
@@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates a new value object containing the specified Mapbox coordinate bounds
structure.
-
+
@param bounds The value for the new object.
@return A new value object that contains the coordinate bounds information.
*/
@@ -59,7 +59,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Creates a new value object containing the given `MGLOfflinePackProgress`
structure.
-
+
@param progress The value for the new object.
@return A new value object that contains the offline pack progress information.
*/
diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp
index 4ca567f55c..7069738fb1 100644
--- a/platform/darwin/src/headless_backend_cgl.cpp
+++ b/platform/darwin/src/headless_backend_cgl.cpp
@@ -1,6 +1,7 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/headless_display.hpp>
+#include <OpenGL/OpenGL.h>
#include <CoreFoundation/CoreFoundation.h>
#include <string>
@@ -8,6 +9,33 @@
namespace mbgl {
+struct CGLImpl : public HeadlessBackend::Impl {
+ CGLImpl(CGLContextObj glContext_) : glContext(glContext_) {
+ }
+
+ ~CGLImpl() {
+ CGLDestroyContext(glContext);
+ }
+
+ void activateContext() final {
+ CGLError error = CGLSetCurrentContext(glContext);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Switching OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+ }
+
+ void deactivateContext() final {
+ CGLError error = CGLSetCurrentContext(nullptr);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Removing OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+ }
+
+ CGLContextObj glContext = nullptr;
+};
+
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
@@ -21,8 +49,18 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
return reinterpret_cast<gl::glProc>(symbol);
}
+bool HeadlessBackend::hasDisplay() {
+ if (!display) {
+ display.reset(new HeadlessDisplay);
+ }
+ return bool(display);
+}
+
void HeadlessBackend::createContext() {
- CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext);
+ assert(!hasContext());
+
+ CGLContextObj glContext = nullptr;
+ CGLError error = CGLCreateContext(display->attribute<CGLPixelFormatObj>(), nullptr, &glContext);
if (error != kCGLNoError) {
throw std::runtime_error(std::string("Error creating GL context object:") +
CGLErrorString(error) + "\n");
@@ -33,26 +71,8 @@ void HeadlessBackend::createContext() {
throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") +
CGLErrorString(error) + "\n");
}
-}
-
-void HeadlessBackend::destroyContext() {
- CGLDestroyContext(glContext);
-}
-
-void HeadlessBackend::activateContext() {
- CGLError error = CGLSetCurrentContext(glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Switching OpenGL context failed:") +
- CGLErrorString(error) + "\n");
- }
-}
-void HeadlessBackend::deactivateContext() {
- CGLError error = CGLSetCurrentContext(nullptr);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Removing OpenGL context failed:") +
- CGLErrorString(error) + "\n");
- }
+ impl.reset(new CGLImpl(glContext));
}
} // namespace mbgl
diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm
index 0a1ae706b8..bd4a202ec5 100644
--- a/platform/darwin/src/headless_backend_eagl.mm
+++ b/platform/darwin/src/headless_backend_eagl.mm
@@ -1,4 +1,4 @@
-#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/gl/extension.hpp>
@@ -8,6 +8,27 @@
namespace mbgl {
+struct EAGLImpl : public HeadlessBackend::Impl {
+ EAGLImpl(EAGLContext* glContext_) : glContext(glContext_) {
+ [reinterpret_cast<EAGLContext*>(glContext) retain];
+ reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
+ }
+
+ ~EAGLImpl() {
+ [glContext release];
+ }
+
+ void activateContext() {
+ [EAGLContext setCurrentContext:glContext];
+ }
+
+ void deactivateContext() {
+ [EAGLContext setCurrentContext:nil];
+ }
+
+ EAGLContext* glContext = nullptr;
+};
+
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
@@ -21,26 +42,17 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
return reinterpret_cast<gl::glProc>(symbol);
}
+bool HeadlessBackend::hasDisplay() {
+ return true;
+}
+
void HeadlessBackend::createContext() {
- glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ EAGLContext* glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (glContext == nil) {
throw std::runtime_error("Error creating GL context object");
}
- [reinterpret_cast<EAGLContext*>(glContext) retain];
- reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
-}
-
-void HeadlessBackend::destroyContext() {
- [reinterpret_cast<EAGLContext*>(glContext) release];
- glContext = nil;
-}
-
-void HeadlessBackend::activateContext() {
- [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
-}
-void HeadlessBackend::deactivateContext() {
- [EAGLContext setCurrentContext:nil];
+ impl.reset(new EAGLImpl(glContext));
}
} // namespace mbgl
diff --git a/platform/darwin/src/headless_display_cgl.cpp b/platform/darwin/src/headless_display_cgl.cpp
new file mode 100644
index 0000000000..5b7a1f2bac
--- /dev/null
+++ b/platform/darwin/src/headless_display_cgl.cpp
@@ -0,0 +1,60 @@
+#include <mbgl/gl/headless_display.hpp>
+
+#include <OpenGL/OpenGL.h>
+
+#include <stdexcept>
+#include <string>
+
+namespace mbgl {
+
+class HeadlessDisplay::Impl {
+public:
+ Impl();
+ ~Impl();
+ CGLPixelFormatObj pixelFormat = nullptr;
+};
+
+HeadlessDisplay::Impl::Impl() {
+ // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported
+ // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
+ CGLPixelFormatAttribute attributes[] = {
+ kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
+ // Not adding kCGLPFAAccelerated, as this will make headless rendering impossible when running in VMs.
+ kCGLPFAClosestPolicy,
+ kCGLPFAAccumSize, static_cast<CGLPixelFormatAttribute>(32),
+ kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(24),
+ kCGLPFAAlphaSize, static_cast<CGLPixelFormatAttribute>(8),
+ kCGLPFADepthSize, static_cast<CGLPixelFormatAttribute>(16),
+ kCGLPFAStencilSize, static_cast<CGLPixelFormatAttribute>(8),
+ kCGLPFASupportsAutomaticGraphicsSwitching,
+ kCGLPFAAllowOfflineRenderers, // Allows using the integrated GPU
+ static_cast<CGLPixelFormatAttribute>(0)
+ };
+
+ GLint num;
+ CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n");
+ }
+ if (num <= 0) {
+ throw std::runtime_error("No pixel formats found.");
+ }
+}
+
+HeadlessDisplay::Impl::~Impl() {
+ CGLDestroyPixelFormat(pixelFormat);
+}
+
+template <>
+CGLPixelFormatObj HeadlessDisplay::attribute() const {
+ return impl->pixelFormat;
+}
+
+HeadlessDisplay::HeadlessDisplay()
+ : impl(std::make_unique<Impl>()) {
+}
+
+HeadlessDisplay::~HeadlessDisplay() {
+}
+
+} // namespace mbgl
diff --git a/platform/darwin/src/http_file_source.mm b/platform/darwin/src/http_file_source.mm
index caac2123d8..649cebb47f 100644
--- a/platform/darwin/src/http_file_source.mm
+++ b/platform/darwin/src/http_file_source.mm
@@ -4,7 +4,6 @@
#include <mbgl/util/http_header.hpp>
#include <mbgl/util/async_task.hpp>
-
#include <mbgl/util/version.hpp>
#import <Foundation/Foundation.h>
@@ -100,7 +99,7 @@ public:
NSURLSession* session = nil;
NSString* userAgent = nil;
NSInteger accountType = 0;
-
+
private:
NSString* getUserAgent() const;
NSBundle* getSDKBundle() const;
@@ -108,7 +107,7 @@ private:
NSString *HTTPFileSource::Impl::getUserAgent() const {
NSMutableArray *userAgentComponents = [NSMutableArray array];
-
+
NSBundle *appBundle = [NSBundle mainBundle];
if (appBundle) {
NSString *appName = appBundle.infoDictionary[@"CFBundleName"];
@@ -118,7 +117,7 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
} else {
[userAgentComponents addObject:[NSProcessInfo processInfo].processName];
}
-
+
NSBundle *sdkBundle = HTTPFileSource::Impl::getSDKBundle();
if (sdkBundle) {
NSString *versionString = sdkBundle.infoDictionary[@"MGLSemanticVersionString"];
@@ -130,12 +129,12 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
sdkBundle.infoDictionary[@"CFBundleName"], versionString]];
}
}
-
+
// Avoid %s here because it inserts hidden bidirectional markers on macOS when the system
// language is set to a right-to-left language.
- [userAgentComponents addObject:[NSString stringWithFormat:@"MapboxGL/%@ (%@)",
- CFSTR(MBGL_VERSION_STRING), CFSTR(MBGL_VERSION_REV)]];
-
+ [userAgentComponents addObject:[NSString stringWithFormat:@"MapboxGL/0.0.0 (%@)",
+ @(mbgl::version::revision)]];
+
NSString *systemName = @"Darwin";
#if TARGET_OS_IPHONE
systemName = @"iOS";
@@ -158,7 +157,7 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
if (systemVersion) {
[userAgentComponents addObject:[NSString stringWithFormat:@"%@/%@", systemName, systemVersion]];
}
-
+
NSString *cpu = nil;
#if TARGET_CPU_X86
cpu = @"x86";
@@ -172,7 +171,7 @@ NSString *HTTPFileSource::Impl::getUserAgent() const {
if (cpu) {
[userAgentComponents addObject:[NSString stringWithFormat:@"(%@)", cpu]];
}
-
+
return [userAgentComponents componentsJoinedByString:@" "];
}
@@ -295,20 +294,20 @@ std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource,
response.error =
std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
} else if (responseCode == 429) {
- //Get the standard header
+ // Get the standard header
optional<std::string> retryAfter;
NSString *retryAfterHeader = headers[@"Retry-After"];
if (retryAfterHeader) {
retryAfter = std::string([retryAfterHeader UTF8String]);
}
-
- //Fallback mapbox specific header
+
+ // Fallback mapbox specific header
optional<std::string> xRateLimitReset;
NSString *xReset = headers[@"x-rate-limit-reset"];
if (xReset) {
xRateLimitReset = std::string([xReset UTF8String]);
}
-
+
response.error = std::make_unique<Error>(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
} else if (responseCode >= 500 && responseCode < 600) {
response.error =
diff --git a/platform/darwin/src/image.mm b/platform/darwin/src/image.mm
index 066535a58c..57b680fbdb 100644
--- a/platform/darwin/src/image.mm
+++ b/platform/darwin/src/image.mm
@@ -1,122 +1,107 @@
-#include <mbgl/util/image.hpp>
+#include <mbgl/util/image+MGLAdditions.hpp>
#import <ImageIO/ImageIO.h>
-#if TARGET_OS_IPHONE
-#import <MobileCoreServices/MobileCoreServices.h>
-#else
-#import <CoreServices/CoreServices.h>
-#endif
-
-namespace mbgl {
-
-std::string encodePNG(const PremultipliedImage& src) {
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, src.data.get(), src.size(), NULL);
+namespace {
+
+template <typename T, typename S, void (*Releaser)(S)>
+struct CFHandle {
+ CFHandle(T t_): t(t_) {}
+ ~CFHandle() { Releaser(t); }
+ T operator*() { return t; }
+ operator bool() { return t; }
+private:
+ T t;
+};
+
+} // namespace
+
+using CGImageHandle = CFHandle<CGImageRef, CGImageRef, CGImageRelease>;
+using CFDataHandle = CFHandle<CFDataRef, CFTypeRef, CFRelease>;
+using CGImageSourceHandle = CFHandle<CGImageSourceRef, CFTypeRef, CFRelease>;
+using CGDataProviderHandle = CFHandle<CGDataProviderRef, CGDataProviderRef, CGDataProviderRelease>;
+using CGColorSpaceHandle = CFHandle<CGColorSpaceRef, CGColorSpaceRef, CGColorSpaceRelease>;
+using CGContextHandle = CFHandle<CGContextRef, CGContextRef, CGContextRelease>;
+
+CGImageRef CGImageFromMGLPremultipliedImage(mbgl::PremultipliedImage&& src) {
+ // We're converting the PremultipliedImage's backing store to a CGDataProvider, and are taking
+ // over ownership of the memory.
+ CGDataProviderHandle provider(CGDataProviderCreateWithData(
+ NULL, src.data.get(), src.bytes(), [](void*, const void* data, size_t) {
+ delete[] reinterpret_cast<const decltype(src.data)::element_type*>(data);
+ }));
if (!provider) {
- return "";
+ return nil;
}
- CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
- if (!color_space) {
- CGDataProviderRelease(provider);
- return "";
- }
+ // If we successfully created the provider, it will take over management of the memory segment.
+ src.data.release();
- CGImageRef image = CGImageCreate(src.width, src.height, 8, 32, 4 * src.width, color_space,
- kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, provider, NULL, false,
- kCGRenderingIntentDefault);
- if (!image) {
- CGColorSpaceRelease(color_space);
- CGDataProviderRelease(provider);
- return "";
+ CGColorSpaceHandle colorSpace(CGColorSpaceCreateDeviceRGB());
+ if (!colorSpace) {
+ return nil;
}
- CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
- if (!data) {
- CGImageRelease(image);
- CGColorSpaceRelease(color_space);
- CGDataProviderRelease(provider);
- return "";
- }
+ constexpr const size_t bitsPerComponent = 8;
+ constexpr const size_t bytesPerPixel = 4;
+ constexpr const size_t bitsPerPixel = bitsPerComponent * bytesPerPixel;
+ const size_t bytesPerRow = bytesPerPixel * src.size.width;
- CGImageDestinationRef image_destination = CGImageDestinationCreateWithData(data, kUTTypePNG, 1, NULL);
- if (!image_destination) {
- CFRelease(data);
- CGImageRelease(image);
- CGColorSpaceRelease(color_space);
- CGDataProviderRelease(provider);
- return "";
+ return CGImageCreate(src.size.width, src.size.height, bitsPerComponent, bitsPerPixel,
+ bytesPerRow, *colorSpace,
+ kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, *provider,
+ NULL, false, kCGRenderingIntentDefault);
+}
+
+mbgl::PremultipliedImage MGLPremultipliedImageFromCGImage(CGImageRef src) {
+ const size_t width = CGImageGetWidth(src);
+ const size_t height = CGImageGetHeight(src);
+
+ mbgl::PremultipliedImage image({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
+
+ CGColorSpaceHandle colorSpace(CGColorSpaceCreateDeviceRGB());
+ if (!colorSpace) {
+ throw std::runtime_error("CGColorSpaceCreateDeviceRGB failed");
}
- CGImageDestinationAddImage(image_destination, image, NULL);
- CGImageDestinationFinalize(image_destination);
+ constexpr const size_t bitsPerComponent = 8;
+ constexpr const size_t bytesPerPixel = 4;
+ const size_t bytesPerRow = bytesPerPixel * width;
- const std::string result {
- reinterpret_cast<const char *>(CFDataGetBytePtr(data)),
- static_cast<size_t>(CFDataGetLength(data))
- };
+ CGContextHandle context(CGBitmapContextCreate(
+ image.data.get(), width, height, bitsPerComponent, bytesPerRow, *colorSpace,
+ kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast));
+ if (!context) {
+ throw std::runtime_error("CGBitmapContextCreate failed");
+ }
- CFRelease(image_destination);
- CFRelease(data);
- CGImageRelease(image);
- CGColorSpaceRelease(color_space);
- CGDataProviderRelease(provider);
+ CGContextSetBlendMode(*context, kCGBlendModeCopy);
+ CGContextDrawImage(*context, CGRectMake(0, 0, width, height), src);
- return result;
+ return image;
}
-PremultipliedImage decodeImage(const std::string &source_data) {
- CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const unsigned char *>(source_data.data()), source_data.size(), kCFAllocatorNull);
+namespace mbgl {
+
+PremultipliedImage decodeImage(const std::string& source) {
+ CFDataHandle data(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, reinterpret_cast<const unsigned char*>(source.data()), source.size(),
+ kCFAllocatorNull));
if (!data) {
throw std::runtime_error("CFDataCreateWithBytesNoCopy failed");
}
- CGImageSourceRef image_source = CGImageSourceCreateWithData(data, NULL);
- if (!image_source) {
- CFRelease(data);
+ CGImageSourceHandle imageSource(CGImageSourceCreateWithData(*data, NULL));
+ if (!imageSource) {
throw std::runtime_error("CGImageSourceCreateWithData failed");
}
- CGImageRef image = CGImageSourceCreateImageAtIndex(image_source, 0, NULL);
+ CGImageHandle image(CGImageSourceCreateImageAtIndex(*imageSource, 0, NULL));
if (!image) {
- CFRelease(image_source);
- CFRelease(data);
throw std::runtime_error("CGImageSourceCreateImageAtIndex failed");
}
- CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
- if (!color_space) {
- CGImageRelease(image);
- CFRelease(image_source);
- CFRelease(data);
- throw std::runtime_error("CGColorSpaceCreateDeviceRGB failed");
- }
-
- PremultipliedImage result{ static_cast<uint16_t>(CGImageGetWidth(image)),
- static_cast<uint16_t>(CGImageGetHeight(image)) };
-
- CGContextRef context = CGBitmapContextCreate(result.data.get(), result.width, result.height, 8, result.stride(),
- color_space, kCGImageAlphaPremultipliedLast);
- if (!context) {
- CGColorSpaceRelease(color_space);
- CGImageRelease(image);
- CFRelease(image_source);
- CFRelease(data);
- throw std::runtime_error("CGBitmapContextCreate failed");
- }
-
- CGContextSetBlendMode(context, kCGBlendModeCopy);
-
- CGRect rect = {{ 0, 0 }, { static_cast<CGFloat>(result.width), static_cast<CGFloat>(result.height) }};
- CGContextDrawImage(context, rect, image);
-
- CGContextRelease(context);
- CGColorSpaceRelease(color_space);
- CGImageRelease(image);
- CFRelease(image_source);
- CFRelease(data);
-
- return result;
+ return MGLPremultipliedImageFromCGImage(*image);
}
-}
+} // namespace mbgl
diff --git a/platform/darwin/src/log_nslog.mm b/platform/darwin/src/logging_nslog.mm
index 49583ae3c4..dd428f56b1 100644
--- a/platform/darwin/src/log_nslog.mm
+++ b/platform/darwin/src/logging_nslog.mm
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/enum.hpp>
#import <Foundation/Foundation.h>
diff --git a/platform/darwin/src/nsthread.mm b/platform/darwin/src/nsthread.mm
index eee6d6991b..6caa1be43e 100644
--- a/platform/darwin/src/nsthread.mm
+++ b/platform/darwin/src/nsthread.mm
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <pthread.h>
diff --git a/platform/darwin/src/run_loop.cpp b/platform/darwin/src/run_loop.cpp
index 63bd8d2f53..bae8164ab6 100644
--- a/platform/darwin/src/run_loop.cpp
+++ b/platform/darwin/src/run_loop.cpp
@@ -7,7 +7,11 @@
namespace mbgl {
namespace util {
-static ThreadLocal<RunLoop>& current = *new ThreadLocal<RunLoop>;
+// Use a static function to avoid the static initialization order fiasco.
+static auto& current() {
+ static ThreadLocal<RunLoop> tl;
+ return tl;
+};
class RunLoop::Impl {
public:
@@ -15,19 +19,20 @@ public:
};
RunLoop* RunLoop::Get() {
- assert(current.get());
- return current.get();
+ assert(current().get());
+ return current().get();
}
RunLoop::RunLoop(Type)
: impl(std::make_unique<Impl>()) {
- assert(!current.get());
- current.set(this);
+ assert(!current().get());
+ current().set(this);
impl->async = std::make_unique<AsyncTask>(std::bind(&RunLoop::process, this));
}
RunLoop::~RunLoop() {
- current.set(nullptr);
+ assert(current().get());
+ current().set(nullptr);
}
void RunLoop::push(std::shared_ptr<WorkTask> task) {
diff --git a/platform/darwin/src/string_nsstring.mm b/platform/darwin/src/string_nsstring.mm
index 9bf199afc0..08f9aeccef 100644
--- a/platform/darwin/src/string_nsstring.mm
+++ b/platform/darwin/src/string_nsstring.mm
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
namespace mbgl {
namespace platform {
diff --git a/platform/darwin/test/MGLAttributionInfoTests.m b/platform/darwin/test/MGLAttributionInfoTests.m
index 3cdb7adffb..74859bda82 100644
--- a/platform/darwin/test/MGLAttributionInfoTests.m
+++ b/platform/darwin/test/MGLAttributionInfoTests.m
@@ -16,7 +16,7 @@
@"CC&nbsp;BY-SA "
@"<a class=\"mapbox-improve-map\" href=\"https://www.mapbox.com/map-feedback/\" target=\"_blank\">Improve this map</a>",
};
-
+
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]
@@ -24,25 +24,25 @@
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);
@@ -54,7 +54,7 @@
static NSString * const htmlStrings[] = {
@"<a href=\"https://www.mapbox.com/\">Mapbox</a>",
};
-
+
CGFloat fontSize = 72;
MGLColor *color = [MGLColor redColor];
NS_MUTABLE_ARRAY_OF(MGLAttributionInfo *) *infos = [NSMutableArray array];
@@ -64,13 +64,13 @@
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
@@ -78,7 +78,7 @@
#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];
@@ -98,7 +98,7 @@
@"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]
@@ -106,7 +106,7 @@
linkColor:nil];
[infos growArrayByAddingAttributionInfosFromArray:subinfos];
}
-
+
XCTAssertEqual(infos.count, 2);
XCTAssertEqualObjects(infos[0].title.string, @"Hello World");
XCTAssertEqualObjects(infos[1].title.string, @"Another Source");
diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
index ec962ae502..92c0ac7cbc 100644
--- a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
+++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -21,107 +21,122 @@
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::BackgroundLayer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::BackgroundLayer>();
-
+
// background-color
{
XCTAssertTrue(rawLayer->getBackgroundColor().isUndefined(),
@"background-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.backgroundColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.backgroundColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.backgroundColor = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
@"Setting backgroundColor to a constant value should update background-color.");
- XCTAssertEqualObjects(layer.backgroundColor, styleValue,
+ XCTAssertEqualObjects(layer.backgroundColor, constantStyleValue,
@"backgroundColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.backgroundColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.backgroundColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
- @"Setting backgroundColor to a function should update background-color.");
- XCTAssertEqualObjects(layer.backgroundColor, styleValue,
- @"backgroundColor should round-trip functions.");
-
+ @"Setting backgroundColor to a camera function should update background-color.");
+ XCTAssertEqualObjects(layer.backgroundColor, functionStyleValue,
+ @"backgroundColor should round-trip camera functions.");
+
+
+
layer.backgroundColor = nil;
XCTAssertTrue(rawLayer->getBackgroundColor().isUndefined(),
@"Unsetting backgroundColor should return background-color to the default value.");
XCTAssertEqualObjects(layer.backgroundColor, defaultStyleValue,
@"backgroundColor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// background-opacity
{
XCTAssertTrue(rawLayer->getBackgroundOpacity().isUndefined(),
@"background-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.backgroundOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.backgroundOpacity = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.backgroundOpacity = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getBackgroundOpacity(), propertyValue,
@"Setting backgroundOpacity to a constant value should update background-opacity.");
- XCTAssertEqualObjects(layer.backgroundOpacity, styleValue,
+ XCTAssertEqualObjects(layer.backgroundOpacity, constantStyleValue,
@"backgroundOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.backgroundOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.backgroundOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getBackgroundOpacity(), propertyValue,
- @"Setting backgroundOpacity to a function should update background-opacity.");
- XCTAssertEqualObjects(layer.backgroundOpacity, styleValue,
- @"backgroundOpacity should round-trip functions.");
-
+ @"Setting backgroundOpacity to a camera function should update background-opacity.");
+ XCTAssertEqualObjects(layer.backgroundOpacity, functionStyleValue,
+ @"backgroundOpacity should round-trip camera functions.");
+
+
+
layer.backgroundOpacity = nil;
XCTAssertTrue(rawLayer->getBackgroundOpacity().isUndefined(),
@"Unsetting backgroundOpacity should return background-opacity to the default value.");
XCTAssertEqualObjects(layer.backgroundOpacity, defaultStyleValue,
@"backgroundOpacity should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// background-pattern
{
XCTAssertTrue(rawLayer->getBackgroundPattern().isUndefined(),
@"background-pattern should be unset initially.");
MGLStyleValue<NSString *> *defaultStyleValue = layer.backgroundPattern;
-
- MGLStyleValue<NSString *> *styleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Background Pattern"];
- layer.backgroundPattern = styleValue;
+
+ MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Background Pattern"];
+ layer.backgroundPattern = constantStyleValue;
mbgl::style::PropertyValue<std::string> propertyValue = { "Background Pattern" };
XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue,
@"Setting backgroundPattern to a constant value should update background-pattern.");
- XCTAssertEqualObjects(layer.backgroundPattern, styleValue,
+ XCTAssertEqualObjects(layer.backgroundPattern, constantStyleValue,
@"backgroundPattern should round-trip constant values.");
+
+ MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.backgroundPattern = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Background Pattern"}} };
+ propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
- styleValue = [MGLStyleValue<NSString *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.backgroundPattern = styleValue;
- propertyValue = { mbgl::style::Function<std::string> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue,
- @"Setting backgroundPattern to a function should update background-pattern.");
- XCTAssertEqualObjects(layer.backgroundPattern, styleValue,
- @"backgroundPattern should round-trip functions.");
-
+ @"Setting backgroundPattern to a camera function should update background-pattern.");
+ XCTAssertEqualObjects(layer.backgroundPattern, functionStyleValue,
+ @"backgroundPattern should round-trip camera functions.");
+
+
+
layer.backgroundPattern = nil;
XCTAssertTrue(rawLayer->getBackgroundPattern().isUndefined(),
@"Unsetting backgroundPattern should return background-pattern to the default value.");
XCTAssertEqualObjects(layer.backgroundPattern, defaultStyleValue,
@"backgroundPattern should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.mm b/platform/darwin/test/MGLCircleStyleLayerTests.mm
index 1f4b82e32b..d7515e8e4e 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.mm
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -20,13 +20,13 @@
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
-
+
XCTAssertNil(layer.sourceLayerIdentifier);
layer.sourceLayerIdentifier = @"layerID";
XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
layer.sourceLayerIdentifier = nil;
XCTAssertNil(layer.sourceLayerIdentifier);
-
+
XCTAssertNil(layer.predicate);
layer.predicate = [NSPredicate predicateWithValue:NO];
XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
@@ -37,254 +37,532 @@
- (void)testProperties {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::CircleLayer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::CircleLayer>();
-
+
// circle-blur
{
XCTAssertTrue(rawLayer->getCircleBlur().isUndefined(),
@"circle-blur should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleBlur;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleBlur = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleBlur = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
@"Setting circleBlur to a constant value should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, styleValue,
+ XCTAssertEqualObjects(layer.circleBlur, constantStyleValue,
@"circleBlur should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleBlur = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleBlur = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
- @"Setting circleBlur to a function should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, styleValue,
- @"circleBlur should round-trip functions.");
-
+ @"Setting circleBlur to a camera function should update circle-blur.");
+ XCTAssertEqualObjects(layer.circleBlur, functionStyleValue,
+ @"circleBlur should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleBlur = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
+ @"Setting circleBlur to a source function should update circle-blur.");
+ XCTAssertEqualObjects(layer.circleBlur, functionStyleValue,
+ @"circleBlur should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleBlur = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
+ @"Setting circleBlur to a composite function should update circle-blur.");
+ XCTAssertEqualObjects(layer.circleBlur, functionStyleValue,
+ @"circleBlur should round-trip composite functions.");
+
+
layer.circleBlur = nil;
XCTAssertTrue(rawLayer->getCircleBlur().isUndefined(),
@"Unsetting circleBlur should return circle-blur to the default value.");
XCTAssertEqualObjects(layer.circleBlur, defaultStyleValue,
@"circleBlur should return the default value after being unset.");
}
-
+
// circle-color
{
XCTAssertTrue(rawLayer->getCircleColor().isUndefined(),
@"circle-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.circleColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.circleColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.circleColor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
@"Setting circleColor to a constant value should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, styleValue,
+ XCTAssertEqualObjects(layer.circleColor, constantStyleValue,
@"circleColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
- @"Setting circleColor to a function should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, styleValue,
- @"circleColor should round-trip functions.");
-
+ @"Setting circleColor to a camera function should update circle-color.");
+ XCTAssertEqualObjects(layer.circleColor, functionStyleValue,
+ @"circleColor should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
+ @"Setting circleColor to a source function should update circle-color.");
+ XCTAssertEqualObjects(layer.circleColor, functionStyleValue,
+ @"circleColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
+ @"Setting circleColor to a composite function should update circle-color.");
+ XCTAssertEqualObjects(layer.circleColor, functionStyleValue,
+ @"circleColor should round-trip composite functions.");
+
+
layer.circleColor = nil;
XCTAssertTrue(rawLayer->getCircleColor().isUndefined(),
@"Unsetting circleColor should return circle-color to the default value.");
XCTAssertEqualObjects(layer.circleColor, defaultStyleValue,
@"circleColor should return the default value after being unset.");
}
-
+
// circle-opacity
{
XCTAssertTrue(rawLayer->getCircleOpacity().isUndefined(),
@"circle-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleOpacity = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleOpacity = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
@"Setting circleOpacity to a constant value should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, styleValue,
+ XCTAssertEqualObjects(layer.circleOpacity, constantStyleValue,
@"circleOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
- @"Setting circleOpacity to a function should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, styleValue,
- @"circleOpacity should round-trip functions.");
-
+ @"Setting circleOpacity to a camera function should update circle-opacity.");
+ XCTAssertEqualObjects(layer.circleOpacity, functionStyleValue,
+ @"circleOpacity should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleOpacity = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
+ @"Setting circleOpacity to a source function should update circle-opacity.");
+ XCTAssertEqualObjects(layer.circleOpacity, functionStyleValue,
+ @"circleOpacity should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleOpacity = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
+ @"Setting circleOpacity to a composite function should update circle-opacity.");
+ XCTAssertEqualObjects(layer.circleOpacity, functionStyleValue,
+ @"circleOpacity should round-trip composite functions.");
+
+
layer.circleOpacity = nil;
XCTAssertTrue(rawLayer->getCircleOpacity().isUndefined(),
@"Unsetting circleOpacity should return circle-opacity to the default value.");
XCTAssertEqualObjects(layer.circleOpacity, defaultStyleValue,
@"circleOpacity should return the default value after being unset.");
}
-
+
// circle-radius
{
XCTAssertTrue(rawLayer->getCircleRadius().isUndefined(),
@"circle-radius should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleRadius;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.circleRadius = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleRadius = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
@"Setting circleRadius to a constant value should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, styleValue,
+ XCTAssertEqualObjects(layer.circleRadius, constantStyleValue,
@"circleRadius should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleRadius = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleRadius = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
- @"Setting circleRadius to a function should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, styleValue,
- @"circleRadius should round-trip functions.");
-
+ @"Setting circleRadius to a camera function should update circle-radius.");
+ XCTAssertEqualObjects(layer.circleRadius, functionStyleValue,
+ @"circleRadius should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleRadius = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
+ @"Setting circleRadius to a source function should update circle-radius.");
+ XCTAssertEqualObjects(layer.circleRadius, functionStyleValue,
+ @"circleRadius should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleRadius = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
+ @"Setting circleRadius to a composite function should update circle-radius.");
+ XCTAssertEqualObjects(layer.circleRadius, functionStyleValue,
+ @"circleRadius should round-trip composite functions.");
+
+
layer.circleRadius = nil;
XCTAssertTrue(rawLayer->getCircleRadius().isUndefined(),
@"Unsetting circleRadius should return circle-radius to the default value.");
XCTAssertEqualObjects(layer.circleRadius, defaultStyleValue,
@"circleRadius should return the default value after being unset.");
}
-
+
// circle-pitch-scale
{
XCTAssertTrue(rawLayer->getCirclePitchScale().isUndefined(),
@"circle-pitch-scale should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.circleScaleAlignment;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCircleScaleAlignment:MGLCircleScaleAlignmentViewport]];
- layer.circleScaleAlignment = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCircleScaleAlignment:MGLCircleScaleAlignmentViewport]];
+ layer.circleScaleAlignment = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::CirclePitchScaleType> propertyValue = { mbgl::style::CirclePitchScaleType::Viewport };
XCTAssertEqual(rawLayer->getCirclePitchScale(), propertyValue,
@"Setting circleScaleAlignment to a constant value should update circle-pitch-scale.");
- XCTAssertEqualObjects(layer.circleScaleAlignment, styleValue,
+ XCTAssertEqualObjects(layer.circleScaleAlignment, constantStyleValue,
@"circleScaleAlignment should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleScaleAlignment = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::CirclePitchScaleType> intervalStops = { {{18, mbgl::style::CirclePitchScaleType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::CirclePitchScaleType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleScaleAlignment = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::CirclePitchScaleType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCirclePitchScale(), propertyValue,
- @"Setting circleScaleAlignment to a function should update circle-pitch-scale.");
- XCTAssertEqualObjects(layer.circleScaleAlignment, styleValue,
- @"circleScaleAlignment should round-trip functions.");
-
+ @"Setting circleScaleAlignment to a camera function should update circle-pitch-scale.");
+ XCTAssertEqualObjects(layer.circleScaleAlignment, functionStyleValue,
+ @"circleScaleAlignment should round-trip camera functions.");
+
+
+
layer.circleScaleAlignment = nil;
XCTAssertTrue(rawLayer->getCirclePitchScale().isUndefined(),
@"Unsetting circleScaleAlignment should return circle-pitch-scale to the default value.");
XCTAssertEqualObjects(layer.circleScaleAlignment, defaultStyleValue,
@"circleScaleAlignment should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
+ // circle-stroke-color
+ {
+ XCTAssertTrue(rawLayer->getCircleStrokeColor().isUndefined(),
+ @"circle-stroke-color should be unset initially.");
+ MGLStyleValue<MGLColor *> *defaultStyleValue = layer.circleStrokeColor;
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.circleStrokeColor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
+ @"Setting circleStrokeColor to a constant value should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, constantStyleValue,
+ @"circleStrokeColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleStrokeColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
+ @"Setting circleStrokeColor to a camera function should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, functionStyleValue,
+ @"circleStrokeColor should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleStrokeColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
+ @"Setting circleStrokeColor to a source function should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, functionStyleValue,
+ @"circleStrokeColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleStrokeColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
+ @"Setting circleStrokeColor to a composite function should update circle-stroke-color.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, functionStyleValue,
+ @"circleStrokeColor should round-trip composite functions.");
+
+
+ layer.circleStrokeColor = nil;
+ XCTAssertTrue(rawLayer->getCircleStrokeColor().isUndefined(),
+ @"Unsetting circleStrokeColor should return circle-stroke-color to the default value.");
+ XCTAssertEqualObjects(layer.circleStrokeColor, defaultStyleValue,
+ @"circleStrokeColor should return the default value after being unset.");
+ }
+
+ // circle-stroke-opacity
+ {
+ XCTAssertTrue(rawLayer->getCircleStrokeOpacity().isUndefined(),
+ @"circle-stroke-opacity should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleStrokeOpacity;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleStrokeOpacity = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
+ @"Setting circleStrokeOpacity to a constant value should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, constantStyleValue,
+ @"circleStrokeOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleStrokeOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
+ @"Setting circleStrokeOpacity to a camera function should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, functionStyleValue,
+ @"circleStrokeOpacity should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleStrokeOpacity = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
+ @"Setting circleStrokeOpacity to a source function should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, functionStyleValue,
+ @"circleStrokeOpacity should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleStrokeOpacity = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
+ @"Setting circleStrokeOpacity to a composite function should update circle-stroke-opacity.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, functionStyleValue,
+ @"circleStrokeOpacity should round-trip composite functions.");
+
+
+ layer.circleStrokeOpacity = nil;
+ XCTAssertTrue(rawLayer->getCircleStrokeOpacity().isUndefined(),
+ @"Unsetting circleStrokeOpacity should return circle-stroke-opacity to the default value.");
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, defaultStyleValue,
+ @"circleStrokeOpacity should return the default value after being unset.");
+ }
+
+ // circle-stroke-width
+ {
+ XCTAssertTrue(rawLayer->getCircleStrokeWidth().isUndefined(),
+ @"circle-stroke-width should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.circleStrokeWidth;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.circleStrokeWidth = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
+ @"Setting circleStrokeWidth to a constant value should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, constantStyleValue,
+ @"circleStrokeWidth should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleStrokeWidth = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
+ @"Setting circleStrokeWidth to a camera function should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, functionStyleValue,
+ @"circleStrokeWidth should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.circleStrokeWidth = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
+ @"Setting circleStrokeWidth to a source function should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, functionStyleValue,
+ @"circleStrokeWidth should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.circleStrokeWidth = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
+ @"Setting circleStrokeWidth to a composite function should update circle-stroke-width.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, functionStyleValue,
+ @"circleStrokeWidth should round-trip composite functions.");
+
+
+ layer.circleStrokeWidth = nil;
+ XCTAssertTrue(rawLayer->getCircleStrokeWidth().isUndefined(),
+ @"Unsetting circleStrokeWidth should return circle-stroke-width to the default value.");
+ XCTAssertEqualObjects(layer.circleStrokeWidth, defaultStyleValue,
+ @"circleStrokeWidth should return the default value after being unset.");
+ }
+
// circle-translate
{
XCTAssertTrue(rawLayer->getCircleTranslate().isUndefined(),
@"circle-translate should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.circleTranslation;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.circleTranslation = styleValue;
+ layer.circleTranslation = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getCircleTranslate(), propertyValue,
@"Setting circleTranslation to a constant value should update circle-translate.");
- XCTAssertEqualObjects(layer.circleTranslation, styleValue,
+ XCTAssertEqualObjects(layer.circleTranslation, constantStyleValue,
@"circleTranslation should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleTranslation = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleTranslation = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCircleTranslate(), propertyValue,
- @"Setting circleTranslation to a function should update circle-translate.");
- XCTAssertEqualObjects(layer.circleTranslation, styleValue,
- @"circleTranslation should round-trip functions.");
-
+ @"Setting circleTranslation to a camera function should update circle-translate.");
+ XCTAssertEqualObjects(layer.circleTranslation, functionStyleValue,
+ @"circleTranslation should round-trip camera functions.");
+
+
+
layer.circleTranslation = nil;
XCTAssertTrue(rawLayer->getCircleTranslate().isUndefined(),
@"Unsetting circleTranslation should return circle-translate to the default value.");
XCTAssertEqualObjects(layer.circleTranslation, defaultStyleValue,
@"circleTranslation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// circle-translate-anchor
{
XCTAssertTrue(rawLayer->getCircleTranslateAnchor().isUndefined(),
@"circle-translate-anchor should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.circleTranslationAnchor;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCircleTranslationAnchor:MGLCircleTranslationAnchorViewport]];
- layer.circleTranslationAnchor = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCircleTranslationAnchor:MGLCircleTranslationAnchorViewport]];
+ layer.circleTranslationAnchor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getCircleTranslateAnchor(), propertyValue,
@"Setting circleTranslationAnchor to a constant value should update circle-translate-anchor.");
- XCTAssertEqualObjects(layer.circleTranslationAnchor, styleValue,
+ XCTAssertEqualObjects(layer.circleTranslationAnchor, constantStyleValue,
@"circleTranslationAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circleTranslationAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.circleTranslationAnchor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TranslateAnchorType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getCircleTranslateAnchor(), propertyValue,
- @"Setting circleTranslationAnchor to a function should update circle-translate-anchor.");
- XCTAssertEqualObjects(layer.circleTranslationAnchor, styleValue,
- @"circleTranslationAnchor should round-trip functions.");
-
+ @"Setting circleTranslationAnchor to a camera function should update circle-translate-anchor.");
+ XCTAssertEqualObjects(layer.circleTranslationAnchor, functionStyleValue,
+ @"circleTranslationAnchor should round-trip camera functions.");
+
+
+
layer.circleTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getCircleTranslateAnchor().isUndefined(),
@"Unsetting circleTranslationAnchor should return circle-translate-anchor to the default value.");
XCTAssertEqualObjects(layer.circleTranslationAnchor, defaultStyleValue,
@"circleTranslationAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}
@@ -294,6 +572,9 @@
[self testPropertyName:@"circle-opacity" isBoolean:NO];
[self testPropertyName:@"circle-radius" isBoolean:NO];
[self testPropertyName:@"circle-scale-alignment" 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-translation" isBoolean:NO];
[self testPropertyName:@"circle-translation-anchor" isBoolean:NO];
}
diff --git a/platform/darwin/test/MGLClockDirectionFormatterTests.m b/platform/darwin/test/MGLClockDirectionFormatterTests.m
index a020ed88b2..13e12ae2f2 100644
--- a/platform/darwin/test/MGLClockDirectionFormatterTests.m
+++ b/platform/darwin/test/MGLClockDirectionFormatterTests.m
@@ -12,59 +12,59 @@ static NSString * const MGLTestLocaleIdentifier = @"en-US";
- (void)testClockDirections {
MGLClockDirectionFormatter *shortFormatter = [[MGLClockDirectionFormatter alloc] init];
shortFormatter.unitStyle = NSFormattingUnitStyleShort;
-
+
MGLClockDirectionFormatter *mediumFormatter = [[MGLClockDirectionFormatter alloc] init];
-
+
MGLClockDirectionFormatter *longFormatter = [[MGLClockDirectionFormatter alloc] init];
longFormatter.unitStyle = NSFormattingUnitStyleLong;
-
+
CLLocationDirection direction;
-
+
direction = -90;
XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 0;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 45;
XCTAssertEqualObjects(@"2:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"2 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"2 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 90;
XCTAssertEqualObjects(@"3:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"3 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"3 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 180;
XCTAssertEqualObjects(@"6:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"6 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"6 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 270;
XCTAssertEqualObjects(@"9:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"9 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 359.34951805867024;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 360;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 360.1;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [longFormatter stringFromDirection:direction]);
-
+
direction = 720;
XCTAssertEqualObjects(@"12:00", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"12 o’clock", [mediumFormatter stringFromDirection:direction]);
diff --git a/platform/darwin/test/MGLCodingTests.m b/platform/darwin/test/MGLCodingTests.m
index b9b299d50f..ff0d674ad1 100644
--- a/platform/darwin/test/MGLCodingTests.m
+++ b/platform/darwin/test/MGLCodingTests.m
@@ -19,11 +19,11 @@
annotation.coordinate = CLLocationCoordinate2DMake(0.5, 0.5);
annotation.title = @"title";
annotation.subtitle = @"subtitle";
-
+
NSString *filePath = [self temporaryFilePathForClass:MGLPointAnnotation.class];
[NSKeyedArchiver archiveRootObject:annotation toFile:filePath];
MGLPointAnnotation *unarchivedAnnotation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(annotation, unarchivedAnnotation);
}
@@ -33,11 +33,11 @@
pointFeature.subtitle = @"subtitle";
pointFeature.identifier = @(123);
pointFeature.attributes = @{@"bbox": @[@1, @2, @3, @4]};
-
+
NSString *filePath = [self temporaryFilePathForClass:MGLPointFeature.class];
[NSKeyedArchiver archiveRootObject:pointFeature toFile:filePath];
MGLPointFeature *unarchivedPointFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(pointFeature, unarchivedPointFeature);
}
@@ -46,25 +46,25 @@
CLLocationCoordinate2DMake(0.129631234123, 1.7812739312551),
CLLocationCoordinate2DMake(2.532083092342, 3.5216418292392)
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
polyline.title = @"title";
polyline.subtitle = @"subtitle";
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPolyline class]];
[NSKeyedArchiver archiveRootObject:polyline toFile:filePath];
MGLPolyline *unarchivedPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(polyline, unarchivedPolyline);
-
+
CLLocationCoordinate2D otherCoordinates[] = {
CLLocationCoordinate2DMake(-1, -2)
};
-
+
[unarchivedPolyline replaceCoordinatesInRange:NSMakeRange(0, 1) withCoordinates:otherCoordinates];
-
+
XCTAssertNotEqualObjects(polyline, unarchivedPolyline);
}
@@ -73,18 +73,18 @@
CLLocationCoordinate2DMake(0.664482398, 1.8865675),
CLLocationCoordinate2DMake(2.13224687, 3.9984632)
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
polygon.title = nil;
polygon.subtitle = @"subtitle";
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]];
[NSKeyedArchiver archiveRootObject:polygon toFile:filePath];
-
+
MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(polygon, unarchivedPolygon);
}
@@ -93,24 +93,24 @@
CLLocationCoordinate2DMake(0, 1),
CLLocationCoordinate2DMake(10, 20)
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
CLLocationCoordinate2D interiorCoordinates[] = {
CLLocationCoordinate2DMake(4, 4),
CLLocationCoordinate2DMake(6, 6)
};
-
+
NSUInteger numberOfInteriorCoordinates = sizeof(interiorCoordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPolygon *interiorPolygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:numberOfInteriorCoordinates];
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates interiorPolygons:@[interiorPolygon]];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPolygon class]];
[NSKeyedArchiver archiveRootObject:polygon toFile:filePath];
-
+
MGLPolygon *unarchivedPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(polygon, unarchivedPolygon);
}
@@ -119,21 +119,21 @@
CLLocationCoordinate2DMake(0, 1),
CLLocationCoordinate2DMake(10, 20)
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates];
polylineFeature.attributes = @{@"bbox": @[@0, @1, @2, @3]};
polylineFeature.identifier = @"identifier";
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPolylineFeature class]];
[NSKeyedArchiver archiveRootObject:polylineFeature toFile:filePath];
-
+
MGLPolylineFeature *unarchivedPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(polylineFeature, unarchivedPolylineFeature);
-
+
unarchivedPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]};
-
+
XCTAssertNotEqualObjects(polylineFeature, unarchivedPolylineFeature);
}
@@ -142,19 +142,19 @@
CLLocationCoordinate2DMake(0, 1),
CLLocationCoordinate2DMake(10, 20)
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPolygonFeature class]];
[NSKeyedArchiver archiveRootObject:polygonFeature toFile:filePath];
-
+
MGLPolygonFeature *unarchivedPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(polygonFeature, unarchivedPolygonFeature);
-
+
unarchivedPolygonFeature.identifier = @"test";
-
+
XCTAssertNotEqualObjects(polygonFeature, unarchivedPolygonFeature);
}
@@ -165,15 +165,15 @@
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPointCollection *pointCollection = [MGLPointCollection pointCollectionWithCoordinates:coordinates count:numberOfCoordinates];
NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollection class]];
[NSKeyedArchiver archiveRootObject:pointCollection toFile:filePath];
-
+
MGLPointCollection *unarchivedPointCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(pointCollection, unarchivedPointCollection);
}
@@ -184,88 +184,88 @@
feature.coordinate = CLLocationCoordinate2DMake(arc4random() % 90, arc4random() % 180);
[features addObject:feature];
}
-
+
CLLocationCoordinate2D coordinates[] = {
CLLocationCoordinate2DMake(0, 1),
CLLocationCoordinate2DMake(10, 11),
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPointCollectionFeature *collection = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:numberOfCoordinates];
collection.identifier = @"identifier";
collection.attributes = @{@"bbox": @[@1, @2, @3, @4]};
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLPointCollectionFeature class]];
[NSKeyedArchiver archiveRootObject:collection toFile:filePath];
-
+
MGLPointCollectionFeature *unarchivedCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(collection, unarchivedCollection);
-
+
unarchivedCollection.identifier = @"newIdentifier";
-
+
XCTAssertNotEqualObjects(collection, unarchivedCollection);
}
- (void)testMultiPolyline {
-
+
CLLocationCoordinate2D coordinates[] = {
CLLocationCoordinate2DMake(0, 1),
CLLocationCoordinate2DMake(10, 11),
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
NSMutableArray *polylines = [NSMutableArray array];
-
+
for (NSUInteger i = 0; i < 100; i++) {
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
[polylines addObject:polyline];
}
-
+
MGLMultiPolyline *multiPolyline = [MGLMultiPolyline multiPolylineWithPolylines:polylines];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolyline class]];
[NSKeyedArchiver archiveRootObject:multiPolyline toFile:filePath];
-
+
MGLMultiPolyline *unarchivedMultiPolyline = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLMultiPolyline *anotherMultipolyline = [MGLMultiPolyline multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]];
-
+
XCTAssertEqualObjects(multiPolyline, unarchivedMultiPolyline);
XCTAssertNotEqualObjects(unarchivedMultiPolyline, anotherMultipolyline);
}
- (void)testMultiPolygon {
-
+
CLLocationCoordinate2D coordinates[] = {
CLLocationCoordinate2DMake(0, 1),
CLLocationCoordinate2DMake(10, 11),
CLLocationCoordinate2DMake(20, 21),
CLLocationCoordinate2DMake(30, 31),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
NSMutableArray *polygons = [NSMutableArray array];
-
+
for (NSUInteger i = 0; i < 100; i++) {
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
[polygons addObject:polygon];
}
-
+
MGLMultiPolygon *multiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:polygons];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolygon class]];
[NSKeyedArchiver archiveRootObject:multiPolygon toFile:filePath];
-
+
MGLMultiPolygon *unarchivedMultiPolygon = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLMultiPolygon *anotherMultiPolygon = [MGLMultiPolygon multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]];
-
+
XCTAssertEqualObjects(multiPolygon, unarchivedMultiPolygon);
XCTAssertNotEqualObjects(anotherMultiPolygon, unarchivedMultiPolygon);
}
@@ -276,20 +276,20 @@
CLLocationCoordinate2DMake(20.91836515, 21.93689215),
CLLocationCoordinate2DMake(30.55697246, 31.33988123),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coordinates count:numberOfCoordinates];
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:coordinates count:numberOfCoordinates];
-
+
MGLShapeCollection *shapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polyline, polygon]];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollection class]];
[NSKeyedArchiver archiveRootObject:shapeCollection toFile:filePath];
-
+
MGLShapeCollection *unarchivedShapeCollection = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLShapeCollection *anotherShapeCollection = [MGLShapeCollection shapeCollectionWithShapes:@[polygon]];
-
+
XCTAssertEqualObjects(shapeCollection, unarchivedShapeCollection);
XCTAssertNotEqualObjects(shapeCollection, anotherShapeCollection);
}
@@ -300,25 +300,25 @@
CLLocationCoordinate2DMake(20.91836515, 21.93689215),
CLLocationCoordinate2DMake(30.55697246, 31.33988123),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
NSMutableArray *polylines = [NSMutableArray array];
for (NSUInteger i = 0; i < 100; i++) {
MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates];
polylineFeature.identifier = @(arc4random() % 100).stringValue;
[polylines addObject:polylineFeature];
}
-
+
MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:polylines];
multiPolylineFeature.attributes = @{@"bbox": @[@4, @3, @2, @1]};
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]];
[NSKeyedArchiver archiveRootObject:multiPolylineFeature toFile:filePath];
-
+
MGLMultiPolylineFeature *unarchivedMultiPolylineFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLMultiPolylineFeature *anotherMultiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:[polylines subarrayWithRange:NSMakeRange(0, polylines.count/2)]];
-
+
XCTAssertEqualObjects(multiPolylineFeature, unarchivedMultiPolylineFeature);
XCTAssertNotEqualObjects(unarchivedMultiPolylineFeature, anotherMultiPolylineFeature);
}
@@ -329,28 +329,28 @@
CLLocationCoordinate2DMake(20.88471238, 21.93684215),
CLLocationCoordinate2DMake(30.15697236, 31.32988123),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
NSMutableArray *polygons = [NSMutableArray array];
for (NSUInteger i = 0; i < 100; i++ ) {
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates];
polygonFeature.identifier = @(arc4random_uniform(100)).stringValue;
[polygons addObject:polygonFeature];
}
-
+
MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:polygons];
multiPolygonFeature.attributes = @{@"bbox": @[@(arc4random_uniform(100)),
@(arc4random_uniform(100)),
@(arc4random_uniform(100)),
@(arc4random_uniform(100))]};
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLMultiPolylineFeature class]];
[NSKeyedArchiver archiveRootObject:multiPolygonFeature toFile:filePath];
-
+
MGLMultiPolygonFeature *unarchivedMultiPolygonFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
MGLMultiPolygonFeature *anotherMultiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:[polygons subarrayWithRange:NSMakeRange(0, polygons.count/2)]];
-
+
XCTAssertEqualObjects(multiPolygonFeature, unarchivedMultiPolygonFeature);
XCTAssertNotEqualObjects(anotherMultiPolygonFeature, unarchivedMultiPolygonFeature);
}
@@ -361,24 +361,24 @@
CLLocationCoordinate2DMake(20.91836515, 21.93689215),
CLLocationCoordinate2DMake(30.55697246, 31.33988123),
};
-
+
NSUInteger numberOfCoordinates = sizeof(coordinates) / sizeof(CLLocationCoordinate2D);
-
+
MGLPolylineFeature *polyline = [MGLPolylineFeature polylineWithCoordinates:coordinates count:numberOfCoordinates];
MGLPolygonFeature *polygon = [MGLPolygonFeature polygonWithCoordinates:coordinates count:numberOfCoordinates];
-
+
MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polyline, polygon]];
shapeCollectionFeature.identifier = @(arc4random_uniform(100)).stringValue;
shapeCollectionFeature.attributes = @{@"bbox":@[@(arc4random_uniform(100)),
@(arc4random_uniform(100)),
@(arc4random_uniform(100)),
@(arc4random_uniform(100))]};
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLShapeCollectionFeature class]];
[NSKeyedArchiver archiveRootObject:shapeCollectionFeature toFile:filePath];
-
+
MGLShapeCollectionFeature *unarchivedShapeCollectionFeature = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(shapeCollectionFeature, unarchivedShapeCollectionFeature);
}
@@ -395,14 +395,14 @@
[[NSColor redColor] drawSwatchInRect:CGRectMake(0, 0, 10, 10)];
[image unlockFocus];
#endif
-
+
MGLAnnotationImage *annotationImage = [MGLAnnotationImage annotationImageWithImage:image reuseIdentifier:@(arc4random_uniform(100)).stringValue];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationImage class]];
[NSKeyedArchiver archiveRootObject:annotationImage toFile:filePath];
-
+
MGLAnnotationImage *unarchivedAnnotationImage = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(annotationImage, unarchivedAnnotationImage);
}
@@ -414,12 +414,12 @@
annotationView.draggable = YES;
annotationView.centerOffset = CGVectorMake(10, 10);
annotationView.scalesWithViewingDistance = NO;
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLAnnotationView class]];
[NSKeyedArchiver archiveRootObject:annotationView toFile:filePath];
-
+
MGLAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled);
XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected);
XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable);
@@ -432,12 +432,12 @@
- (void)testUserLocation {
MGLUserLocation *userLocation = [[MGLUserLocation alloc] init];
userLocation.location = [[CLLocation alloc] initWithLatitude:1 longitude:1];
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocation class]];
[NSKeyedArchiver archiveRootObject:userLocation toFile:filePath];
-
+
MGLUserLocation *unarchivedUserLocation = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqualObjects(userLocation, unarchivedUserLocation);
unarchivedUserLocation.location = [[CLLocation alloc] initWithLatitude:10 longitude:10];
XCTAssertNotEqualObjects(userLocation, unarchivedUserLocation);
@@ -452,12 +452,12 @@
annotationView.draggable = YES;
annotationView.centerOffset = CGVectorMake(10, 10);
annotationView.scalesWithViewingDistance = NO;
-
+
NSString *filePath = [self temporaryFilePathForClass:[MGLUserLocationAnnotationView class]];
[NSKeyedArchiver archiveRootObject:annotationView toFile:filePath];
-
+
MGLUserLocationAnnotationView *unarchivedAnnotationView = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
-
+
XCTAssertEqual(annotationView.enabled, unarchivedAnnotationView.enabled);
XCTAssertEqual(annotationView.selected, unarchivedAnnotationView.selected);
XCTAssertEqual(annotationView.draggable, unarchivedAnnotationView.draggable);
diff --git a/platform/darwin/test/MGLCompassDirectionFormatterTests.m b/platform/darwin/test/MGLCompassDirectionFormatterTests.m
index bba0317ebf..c4ccc6ac4f 100644
--- a/platform/darwin/test/MGLCompassDirectionFormatterTests.m
+++ b/platform/darwin/test/MGLCompassDirectionFormatterTests.m
@@ -10,75 +10,75 @@
- (void)testCompassDirections {
MGLCompassDirectionFormatter *shortFormatter = [[MGLCompassDirectionFormatter alloc] init];
shortFormatter.unitStyle = NSFormattingUnitStyleShort;
-
+
MGLCompassDirectionFormatter *mediumFormatter = [[MGLCompassDirectionFormatter alloc] init];
XCTAssertEqual(mediumFormatter.unitStyle, NSFormattingUnitStyleMedium, @"Unit style should be medium by default.");
-
+
MGLCompassDirectionFormatter *longFormatter = [[MGLCompassDirectionFormatter alloc] init];
longFormatter.unitStyle = NSFormattingUnitStyleLong;
-
+
CLLocationDirection direction;
-
+
direction = -45;
XCTAssertEqualObjects(@"NW", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"northwest", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"northwest", [longFormatter stringFromDirection:direction]);
-
+
direction = 0;
XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]);
-
+
direction = 1;
XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]);
-
+
direction = 10;
XCTAssertEqualObjects(@"NbE", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north by east", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north by east", [longFormatter stringFromDirection:direction]);
-
+
direction = 20;
XCTAssertEqualObjects(@"NNE", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north-northeast", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north-northeast", [longFormatter stringFromDirection:direction]);
-
+
direction = 45;
XCTAssertEqualObjects(@"NE", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"northeast", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"northeast", [longFormatter stringFromDirection:direction]);
-
+
direction = 90;
XCTAssertEqualObjects(@"E", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"east", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"east", [longFormatter stringFromDirection:direction]);
-
+
direction = 180;
XCTAssertEqualObjects(@"S", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"south", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"south", [longFormatter stringFromDirection:direction]);
-
+
direction = 270;
XCTAssertEqualObjects(@"W", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"west", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"west", [longFormatter stringFromDirection:direction]);
-
+
direction = 359.34951805867024;
XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]);
-
+
direction = 360;
XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]);
-
+
direction = 360.1;
XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [longFormatter stringFromDirection:direction]);
-
+
direction = 720;
XCTAssertEqualObjects(@"N", [shortFormatter stringFromDirection:direction]);
XCTAssertEqualObjects(@"north", [mediumFormatter stringFromDirection:direction]);
diff --git a/platform/darwin/test/MGLCoordinateFormatterTests.m b/platform/darwin/test/MGLCoordinateFormatterTests.m
index 6a6c7a3b2e..ac083fa103 100644
--- a/platform/darwin/test/MGLCoordinateFormatterTests.m
+++ b/platform/darwin/test/MGLCoordinateFormatterTests.m
@@ -12,33 +12,33 @@
shortFormatter.unitStyle = NSFormattingUnitStyleShort;
XCTAssertTrue(shortFormatter.allowsSeconds, @"Arcseconds should be allowed by default.");
XCTAssertTrue(shortFormatter.allowsMinutes, @"Arcminutes should be allowed by default.");
-
+
MGLCoordinateFormatter *mediumFormatter = [[MGLCoordinateFormatter alloc] init];
XCTAssertEqual(mediumFormatter.unitStyle, NSFormattingUnitStyleMedium, @"Unit style should be medium by default.");
-
+
MGLCoordinateFormatter *longFormatter = [[MGLCoordinateFormatter alloc] init];
longFormatter.unitStyle = NSFormattingUnitStyleLong;
-
+
CLLocationCoordinate2D coordinate;
-
+
coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239);
XCTAssertEqualObjects([shortFormatter stringFromCoordinate:coordinate], @"38°54′48″N, 77°1′57″W");
XCTAssertEqualObjects([mediumFormatter stringFromCoordinate:coordinate], @"38°54′48″ north, 77°1′57″ west");
XCTAssertEqualObjects([longFormatter stringFromCoordinate:coordinate], @"38 degrees, 54 minutes, and 48 seconds north by 77 degrees, 1 minute, and 57 seconds west");
-
+
shortFormatter.allowsSeconds = NO;
mediumFormatter.allowsSeconds = NO;
longFormatter.allowsSeconds = NO;
-
+
coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239);
XCTAssertEqualObjects([shortFormatter stringFromCoordinate:coordinate], @"38°55′N, 77°2′W");
XCTAssertEqualObjects([mediumFormatter stringFromCoordinate:coordinate], @"38°55′ north, 77°2′ west");
XCTAssertEqualObjects([longFormatter stringFromCoordinate:coordinate], @"38 degrees and 55 minutes north by 77 degrees and 2 minutes west");
-
+
shortFormatter.allowsMinutes = NO;
mediumFormatter.allowsMinutes = NO;
longFormatter.allowsMinutes = NO;
-
+
coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239);
XCTAssertEqualObjects([shortFormatter stringFromCoordinate:coordinate], @"39°N, 77°W");
XCTAssertEqualObjects([mediumFormatter stringFromCoordinate:coordinate], @"39° north, 77° west");
diff --git a/platform/darwin/test/MGLDistanceFormatterTests.m b/platform/darwin/test/MGLDistanceFormatterTests.m
new file mode 100644
index 0000000000..f15ad9d313
--- /dev/null
+++ b/platform/darwin/test/MGLDistanceFormatterTests.m
@@ -0,0 +1,30 @@
+#import <Mapbox/Mapbox.h>
+#import <XCTest/XCTest.h>
+
+@interface MGLDistanceFormatterTests : XCTestCase
+
+@end
+
+@implementation MGLDistanceFormatterTests
+
+- (void)testAbbreviatedMetricUnits {
+ MGLDistanceFormatter *formatter = [[MGLDistanceFormatter alloc] init];
+ formatter.numberFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_CA"];
+ for (CLLocationDistance distance=0; distance <= 10000; distance+=5) {
+ NSString *unit = [[formatter stringFromDistance:distance] componentsSeparatedByString:@" "][1];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", @[@"mm", @"cm", @"m", @"km"]];
+ XCTAssert([predicate evaluateWithObject:unit], @"Should only contain metric units");
+ }
+}
+
+- (void)testAbbreviatedImperialUnits {
+ MGLDistanceFormatter *formatter = [[MGLDistanceFormatter alloc] init];
+ formatter.numberFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
+ for (CLLocationDistance distance=0; distance <= 10000; distance+=5) {
+ NSString *unit = [[formatter stringFromDistance:distance] componentsSeparatedByString:@" "][1];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", @[@"ft", @"mi"]];
+ XCTAssert([predicate evaluateWithObject:unit], @"Should only contain imperial units");
+ }
+}
+
+@end
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 9336db7e49..177d97d523 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -112,10 +112,10 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
let layer = MGLCircleStyleLayer(identifier: "circles", source: population)
layer.sourceLayerIdentifier = "population"
layer.circleColor = MGLStyleValue(rawValue: .green)
- layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [
- 12: MGLStyleValue(rawValue: 2),
- 22: MGLStyleValue(rawValue: 180)
- ])
+ layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: [12: MGLStyleValue(rawValue: 2),
+ 22: MGLStyleValue(rawValue: 180)],
+ options: [.interpolationBase: 1.75])
layer.circleOpacity = MGLStyleValue(rawValue: 0.7)
layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married")
mapView.style?.addLayer(layer)
@@ -131,10 +131,10 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
//#-example-code
let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
layer.sourceLayerIdentifier = "trails"
- layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [
- 14: MGLStyleValue(rawValue: 2),
- 18: MGLStyleValue(rawValue: 20),
- ])
+ layer.lineWidth = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: [14: MGLStyleValue(rawValue: 2),
+ 18: MGLStyleValue(rawValue: 20)],
+ options: [.interpolationBase: 1.5])
layer.lineColor = MGLStyleValue(rawValue: .brown)
layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round))
layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking")
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index 00b57c15f0..ad0833a068 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -2,8 +2,29 @@
#import <string>
+#import "MGLTypes.h"
#import "NSExpression+MGLAdditions.h"
+#define MGLAssertEqualValues(actual, expected, ...) \
+ XCTAssertTrue(actual.is<__typeof__(expected)>()); \
+ if (actual.is<__typeof__(expected)>()) { \
+ XCTAssertEqual(actual.get<__typeof__(expected)>(), expected, __VA_ARGS__); \
+ }
+
+#define MGLAssertEqualValuesWithAccuracy(actual, expected, accuracy, ...) \
+ XCTAssertTrue(actual.is<__typeof__(expected)>()); \
+ if (actual.is<__typeof__(expected)>()) { \
+ XCTAssertEqualWithAccuracy(actual.get<__typeof__(expected)>(), expected, accuracy, __VA_ARGS__); \
+ }
+
+#define MGLAssertConstantEqualsValue(constant, value, ...) \
+ MGLAssertEqualValues([NSExpression expressionForConstantValue:constant].mgl_constantMBGLValue, value, __VA_ARGS__);
+
+#define MGLAssertConstantEqualsValueWithAccuracy(constant, value, accuracy, ...) \
+ MGLAssertEqualValuesWithAccuracy([NSExpression expressionForConstantValue:constant].mgl_constantMBGLValue, value, accuracy, __VA_ARGS__);
+
+using namespace std::string_literals;
+
@interface MGLExpressionTests : XCTestCase
@end
@@ -23,193 +44,100 @@
return predicate;
}
-#pragma mark - String Tests
+#pragma mark - Valuation tests
-- (void)testExpressionConversionString
-{
- NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@"bar"];
- mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<std::string>());
- XCTAssertEqualObjects(@(convertedValue.get<std::string>().c_str()), @"bar");
+- (void)testStringValuation {
+ MGLAssertConstantEqualsValue(@"bar", "bar"s, @"NSString should convert to std::string.");
+ MGLAssertConstantEqualsValue(@"🆔🆗🇦🇶", "🆔🆗🇦🇶"s, @"NSString with non-ASCII characters should convert losslessly to std::string.");
}
-- (void)testExpressionConversionStringWithUnicode
-{
- NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@"🆔🆗🇦🇶"];
- mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<std::string>());
- XCTAssertEqual(convertedValue.get<std::string>(), "🆔🆗🇦🇶");
+- (void)testColorValuation {
+ MGLAssertConstantEqualsValue([MGLColor redColor], "rgba(255,0,0,1)"s, @"MGLColor should convert to std::string containing CSS color string.");
}
-#pragma mark - Boolean Tests
-
-- (void)testExpressionConversionBooleanTrue
-{
- NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@YES];
- mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<bool>());
- XCTAssertEqual(convertedValue.get<bool>(), true);
+- (void)testBooleanValuation {
+ MGLAssertConstantEqualsValue(@NO, false, @"Boolean NSNumber should convert to bool.");
+ MGLAssertConstantEqualsValue(@YES, true, @"Boolean NSNumber should convert to bool.");
}
-- (void)testExpressionConversionBooleanFalse
-{
- NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@NO];
- mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<bool>());
- XCTAssertEqual(convertedValue.get<bool>(), false);
-}
-
-#pragma mark - Floating Point Tests
-
-- (void)testExpressionConversionDouble
+- (void)testDoubleValuation
{
- NSComparisonPredicate *predicate;
- mbgl::Value convertedValue;
-
- predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithDouble:DBL_MIN]];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<double>());
- XCTAssertEqual(convertedValue.get<double>(), DBL_MIN);
-
- predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithDouble:DBL_MAX]];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<double>());
- XCTAssertEqual(convertedValue.get<double>(), DBL_MAX);
+ MGLAssertConstantEqualsValue(@DBL_MIN, DBL_MIN, @"Double NSNumber should convert to double.");
+ MGLAssertConstantEqualsValue(@DBL_MAX, DBL_MAX, @"Double NSNumber should convert to double.");
}
-- (void)testExpressionConversionFloat
-{
+- (void)testFloatValuation {
// Because we can't guarantee precision when using float, and because
// we warn the user to this effect in -[NSExpression mgl_constantMBGLValue],
// we just check that things are in the ballpark here with integer values
// and some lower-precision checks.
-
- NSComparisonPredicate *predicate;
- mbgl::Value convertedValue;
-
- predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:-1]];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<double>());
- XCTAssertEqual(convertedValue.get<double>(), -1);
-
- predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:1]];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<double>());
- XCTAssertEqual(convertedValue.get<double>(), 1);
-
- predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:-23.232342]];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<double>());
- XCTAssertEqualWithAccuracy(convertedValue.get<double>(), -23.232342, 0.000001);
-
- predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:23.232342]];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<double>());
- XCTAssertEqualWithAccuracy(convertedValue.get<double>(), 23.232342, 0.000001);
+
+ MGLAssertConstantEqualsValue(@-1.0f, -1.0, @"Float NSNumber should convert to double.");
+ MGLAssertConstantEqualsValue(@1.0f, 1.0, @"Float NSNumber should convert to double.");
+ MGLAssertConstantEqualsValueWithAccuracy(@-23.232342f, -23.232342, 0.000001, @"Float NSNumber should convert to double.");
+ MGLAssertConstantEqualsValueWithAccuracy(@23.232342f, 23.232342, 0.000001, @"Float NSNumber should convert to double.");
+ MGLAssertConstantEqualsValueWithAccuracy(@-FLT_MAX, static_cast<double>(-FLT_MAX), 0.000001, @"Float NSNumber should convert to double.");
+ MGLAssertConstantEqualsValueWithAccuracy(@FLT_MAX, static_cast<double>(FLT_MAX), 0.000001, @"Float NSNumber should convert to double.");
}
-#pragma mark - Integer Tests
-
-- (void)testExpressionNegativeIntegers
-{
- NSComparisonPredicate *predicate;
- mbgl::Value convertedValue;
-
- NSArray<NSNumber *> *minValues = @[
- [NSNumber numberWithShort: SHRT_MIN],
- [NSNumber numberWithInt: INT_MIN],
- [NSNumber numberWithLong: LONG_MIN],
- [NSNumber numberWithLongLong: LLONG_MIN],
- [NSNumber numberWithInteger: NSIntegerMin]
- ];
-
- NSArray<NSNumber *> *maxValues = @[
- [NSNumber numberWithShort: SHRT_MAX],
- [NSNumber numberWithInt: INT_MAX],
- [NSNumber numberWithLong: LONG_MAX],
- [NSNumber numberWithLongLong: LLONG_MAX],
- [NSNumber numberWithInteger: NSIntegerMax]
- ];
-
+- (void)testIntegerValuation {
// Negative integers should always come back as int64_t per mbgl::Value definition.
- // We use the long long value because it can store the highest number on both 32-
- // and 64-bit and won't overflow.
-
- for (NSNumber *min in minValues)
- {
- predicate = [self equalityComparisonPredicateWithRightConstantValue:min];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<int64_t>());
- XCTAssertEqual(convertedValue.get<int64_t>(), min.longLongValue);
- }
+ MGLAssertConstantEqualsValue(@SHRT_MIN, static_cast<int64_t>(SHRT_MIN), @"Negative short NSNumber should convert to int64_t.");
+ MGLAssertConstantEqualsValue(@INT_MIN, static_cast<int64_t>(INT_MIN), @"Negative int NSNumber should convert to int64_t.");
+ MGLAssertConstantEqualsValue(@LONG_MIN, static_cast<int64_t>(LONG_MIN), @"Negative long NSNumber should convert to int64_t.");
+ MGLAssertConstantEqualsValue(@LLONG_MIN, static_cast<int64_t>(LLONG_MIN), @"Negative long long NSNumber should convert to int64_t.");
+ MGLAssertConstantEqualsValue(@NSIntegerMin, static_cast<int64_t>(NSIntegerMin), @"Negative NSInteger NSNumber should convert to int64_t.");
// Positive integers should always come back as uint64_t per mbgl::Value definition.
- // We use the unsigned long long value because it can store the highest number on
- // both 32- and 64-bit and won't overflow.
-
- for (NSNumber *max in maxValues)
- {
- predicate = [self equalityComparisonPredicateWithRightConstantValue:max];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<uint64_t>());
- XCTAssertEqual(convertedValue.get<uint64_t>(), max.unsignedLongLongValue);
- }
-
+ MGLAssertConstantEqualsValue(@SHRT_MAX, static_cast<uint64_t>(SHRT_MAX), @"Positive short NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@INT_MAX, static_cast<uint64_t>(INT_MAX), @"Positive int NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@LONG_MAX, static_cast<uint64_t>(LONG_MAX), @"Positive long NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@LLONG_MAX, static_cast<uint64_t>(LLONG_MAX), @"Positive long long NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@NSIntegerMax, static_cast<uint64_t>(NSIntegerMax), @"Positive NSInteger NSNumber should convert to uint64_t.");
}
-- (void)testExpressionPositiveAndZeroIntegers
-{
- NSComparisonPredicate *predicate;
- mbgl::Value convertedValue;
-
- NSArray<NSNumber *> *minValues = @[
- [NSNumber numberWithUnsignedShort: 0],
- [NSNumber numberWithUnsignedInt: 0],
- [NSNumber numberWithUnsignedLong: 0],
- [NSNumber numberWithUnsignedLongLong: 0],
- [NSNumber numberWithUnsignedInteger: 0]
- ];
-
- NSArray<NSNumber *> *maxValues = @[
- [NSNumber numberWithUnsignedShort: USHRT_MAX],
- [NSNumber numberWithUnsignedInt: UINT_MAX],
- [NSNumber numberWithUnsignedLong: ULONG_MAX],
- [NSNumber numberWithUnsignedLongLong: ULLONG_MAX],
- [NSNumber numberWithUnsignedInteger: NSUIntegerMax]
- ];
-
+- (void)testUnsignedIntegerValuation {
// Zero-value integers should always come back as uint64_t per mbgl::Value definition
// (using the interpretation that zero is not negative). We use the unsigned long long
// value just for parity with the positive integer test.
-
- for (NSNumber *min in minValues)
- {
- predicate = [self equalityComparisonPredicateWithRightConstantValue:min];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<uint64_t>());
- XCTAssertEqual(convertedValue.get<uint64_t>(), min.unsignedLongLongValue);
- }
+ MGLAssertConstantEqualsValue(@(static_cast<unsigned short>(0)), static_cast<uint64_t>(0), @"Unsigned short NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@0u, static_cast<uint64_t>(0), @"Unsigned int NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@0UL, static_cast<uint64_t>(0), @"Unsigned long NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@0ULL, static_cast<uint64_t>(0), @"Unsigned long long NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@(static_cast<NSUInteger>(0)), static_cast<uint64_t>(0), @"Unsigned NSUInteger NSNumber should convert to uint64_t.");
// Positive integers should always come back as uint64_t per mbgl::Value definition.
// We use the unsigned long long value because it can store the highest number on
// both 32- and 64-bit and won't overflow.
-
- for (NSNumber *max in maxValues)
- {
- predicate = [self equalityComparisonPredicateWithRightConstantValue:max];
- convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<uint64_t>());
- XCTAssertEqual(convertedValue.get<uint64_t>(), max.unsignedLongLongValue);
- }
+ MGLAssertConstantEqualsValue(@USHRT_MAX, static_cast<uint64_t>(USHRT_MAX), @"Unsigned short NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@UINT_MAX, static_cast<uint64_t>(UINT_MAX), @"Unsigned int NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@ULONG_MAX, static_cast<uint64_t>(ULONG_MAX), @"Unsigned long NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@ULLONG_MAX, static_cast<uint64_t>(ULLONG_MAX), @"Unsigned long long NSNumber should convert to uint64_t.");
+ MGLAssertConstantEqualsValue(@NSUIntegerMax, static_cast<uint64_t>(NSUIntegerMax), @"Unsigned NSUInteger NSNumber should convert to uint64_t.");
}
-#pragma mark - Null Tests
+- (void)testNullValuation {
+ mbgl::NullValue nullValue;
+ MGLAssertConstantEqualsValue([NSNull null], nullValue, @"NSNull should convert to mbgl::NullValue.");
+}
-- (void)testExpressionConversionNull
-{
- NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNull null]];
- mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue;
- XCTAssertTrue(convertedValue.is<mbgl::NullValue>());
+#pragma mark - Feature type tests
+
+- (void)testFeatureType {
+ XCTAssertEqual([NSExpression expressionForConstantValue:@"Point"].mgl_featureType, mbgl::FeatureType::Point);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@"LineString"].mgl_featureType, mbgl::FeatureType::LineString);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@"Polygon"].mgl_featureType, mbgl::FeatureType::Polygon);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@"Unknown"].mgl_featureType, mbgl::FeatureType::Unknown);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@""].mgl_featureType, mbgl::FeatureType::Unknown);
+
+ XCTAssertEqual([NSExpression expressionForConstantValue:@1].mgl_featureType, mbgl::FeatureType::Point);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@2].mgl_featureType, mbgl::FeatureType::LineString);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@3].mgl_featureType, mbgl::FeatureType::Polygon);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@0].mgl_featureType, mbgl::FeatureType::Unknown);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@-1].mgl_featureType, mbgl::FeatureType::Unknown);
+ XCTAssertEqual([NSExpression expressionForConstantValue:@4].mgl_featureType, mbgl::FeatureType::Unknown);
+
+ XCTAssertEqual([NSExpression expressionForConstantValue:nil].mgl_featureType, mbgl::FeatureType::Unknown);
}
@end
diff --git a/platform/darwin/test/MGLFeatureTests.mm b/platform/darwin/test/MGLFeatureTests.mm
index 7d60f53faa..818ad8200e 100644
--- a/platform/darwin/test/MGLFeatureTests.mm
+++ b/platform/darwin/test/MGLFeatureTests.mm
@@ -12,16 +12,16 @@
- (void)testGeometryConversion {
std::vector<mbgl::Feature> features;
-
+
mbgl::Point<double> point = { -90.066667, 29.95 };
features.push_back(mbgl::Feature { point });
-
+
mbgl::LineString<double> lineString = {
{ -84.516667, 39.1 },
{ -90.066667, 29.95 },
};
features.push_back(mbgl::Feature { lineString });
-
+
mbgl::Polygon<double> polygon = {
{
{ 1, 1 },
@@ -37,15 +37,15 @@
},
};
features.push_back(mbgl::Feature { polygon });
-
+
NS_ARRAY_OF(MGLShape <MGLFeature> *) *shapes = MGLFeaturesFromMBGLFeatures(features);
XCTAssertEqual(shapes.count, 3, @"All features should be converted into shapes");
-
+
MGLPointFeature *pointShape = (MGLPointFeature *)shapes[0];
XCTAssertTrue([pointShape isKindOfClass:[MGLPointFeature class]]);
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:pointShape.coordinate],
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(29.95, -90.066667)]);
-
+
MGLPolylineFeature *polylineShape = (MGLPolylineFeature *)shapes[1];
XCTAssertTrue([polylineShape isKindOfClass:[MGLPolylineFeature class]]);
XCTAssertEqual(polylineShape.pointCount, 2);
@@ -55,7 +55,7 @@
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(39.1, -84.516667)]);
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:polylineCoordinates[1]],
[NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(29.95, -90.066667)]);
-
+
MGLPolygonFeature *polygonShape = (MGLPolygonFeature *)shapes[2];
XCTAssertTrue([polygonShape isKindOfClass:[MGLPolygonFeature class]]);
XCTAssertEqual(polygonShape.pointCount, 4);
@@ -87,11 +87,11 @@
- (void)testPropertyConversion {
std::vector<mbgl::Feature> features;
-
+
mbgl::Point<double> point = { -90.066667, 29.95 };
mbgl::Feature pointFeature { point };
pointFeature.id = { UINT64_MAX };
- pointFeature.properties["null"] = nullptr;
+ pointFeature.properties["null"] = mapbox::geometry::null_value;
pointFeature.properties["bool"] = true;
pointFeature.properties["unsigned int"] = UINT64_MAX;
pointFeature.properties["int"] = INT64_MIN;
@@ -102,23 +102,23 @@
vector.push_back(false);
vector.push_back(true);
features.push_back(pointFeature);
-
+
NS_ARRAY_OF(MGLShape <MGLFeature> *) *shapes = MGLFeaturesFromMBGLFeatures(features);
XCTAssertEqual(shapes.count, 1, @"All features should be converted into shapes");
-
+
MGLShape <MGLFeature> *shape = shapes.firstObject;
XCTAssertTrue([shape conformsToProtocol:@protocol(MGLFeature)]);
XCTAssertTrue([shape isKindOfClass:[MGLShape class]]);
-
+
NSNumber *identifier = shape.identifier;
XCTAssertTrue([identifier isKindOfClass:[NSNumber class]], @"Feature identifier should be NSNumber");
XCTAssertEqual(strcmp(identifier.objCType, @encode(uint64_t)), 0, @"Feature identifier should be 64-bit unsigned integer");
-
+
NSNull *null = [shape attributeForKey:@"null"];
XCTAssertNotNil(null);
XCTAssertTrue([null isKindOfClass:[NSNull class]]);
XCTAssertEqual(null, shape.attributes[@"null"]);
-
+
NSNumber *boolean = [shape attributeForKey:@"bool"];
XCTAssertNotNil(boolean);
XCTAssertTrue([boolean isKindOfClass:[NSNumber class]]);
@@ -129,28 +129,28 @@
#endif
XCTAssertTrue(boolean.boolValue);
XCTAssertEqual(boolean, shape.attributes[@"bool"]);
-
+
NSNumber *unsignedInteger = [shape attributeForKey:@"unsigned int"];
XCTAssertNotNil(unsignedInteger);
XCTAssertTrue([unsignedInteger isKindOfClass:[NSNumber class]]);
XCTAssertEqual(strcmp(unsignedInteger.objCType, @encode(uint64_t)), 0, @"Unsigned integer property should be converted to unsigned long long NSNumber");
XCTAssertEqual(unsignedInteger.unsignedLongLongValue, UINT64_MAX);
XCTAssertEqual(unsignedInteger, shape.attributes[@"unsigned int"]);
-
+
NSNumber *integer = [shape attributeForKey:@"int"];
XCTAssertNotNil(integer);
XCTAssertTrue([integer isKindOfClass:[NSNumber class]]);
XCTAssertEqual(strcmp(integer.objCType, @encode(int64_t)), 0, @"Integer property should be converted to long long NSNumber");
XCTAssertEqual(integer.longLongValue, INT64_MIN);
XCTAssertEqual(integer, shape.attributes[@"int"]);
-
+
NSNumber *floatingPointNumber = [shape attributeForKey:@"double"];
XCTAssertNotNil(floatingPointNumber);
XCTAssertTrue([floatingPointNumber isKindOfClass:[NSNumber class]]);
XCTAssertEqual(strcmp(floatingPointNumber.objCType, @encode(double)), 0, @"Floating-point number property should be converted to double NSNumber");
XCTAssertEqual(floatingPointNumber.doubleValue, DBL_MAX);
XCTAssertEqual(floatingPointNumber, shape.attributes[@"double"]);
-
+
NSString *string = [shape attributeForKey:@"string"];
XCTAssertNotNil(string);
XCTAssertTrue([string isKindOfClass:[NSString class]]);
@@ -162,11 +162,11 @@
MGLPointFeature *pointFeature = [[MGLPointFeature alloc] init];
CLLocationCoordinate2D coordinate = { 10, 10 };
pointFeature.coordinate = coordinate;
-
+
// A GeoJSON feature
// when there are no identifier or properties
NSDictionary *geoJSONFeature = [pointFeature geoJSONDictionary];
-
+
// it has the correct type
XCTAssertEqualObjects(geoJSONFeature[@"type"], @"Feature");
// it has the correct geometry
@@ -177,17 +177,17 @@
XCTAssertNil(geoJSONFeature[@"id"]);
// it has a null representation of the properties object
XCTAssertEqualObjects(geoJSONFeature[@"properties"], [NSNull null]);
-
+
// when there is a string identifier
pointFeature.identifier = @"string-id";
-
+
// it has the identifier in the result
geoJSONFeature = [pointFeature geoJSONDictionary];
XCTAssertEqualObjects(geoJSONFeature[@"id"], pointFeature.identifier);
-
+
// when there are properties
pointFeature.attributes = @{@"name": @"name-value"};
-
+
// it has the properties value in the result
geoJSONFeature = [pointFeature geoJSONDictionary];
XCTAssertEqualObjects(geoJSONFeature[@"properties"], pointFeature.attributes);
@@ -198,10 +198,10 @@
CLLocationCoordinate2D coord2 = { 10, 10 };
CLLocationCoordinate2D coords[] = { coord1, coord2 };
MGLPolylineFeature *polyLineFeature = [MGLPolylineFeature polylineWithCoordinates:coords count:2];
-
+
// A GeoJSON feature
NSDictionary *geoJSONFeature = [polyLineFeature geoJSONDictionary];
-
+
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"LineString",
@"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
@@ -215,10 +215,10 @@
CLLocationCoordinate2D coord3 = { 0, 0 };
CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coords count:3];
-
+
// A GeoJSON feature
NSDictionary *geoJSONFeature = [polygonFeature geoJSONDictionary];
-
+
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"Polygon",
@"coordinates": @[@[@[@(coord1.longitude), @(coord1.latitude)],
@@ -232,15 +232,15 @@
CLLocationCoordinate2D coord2 = { 10, 10 };
CLLocationCoordinate2D coord3 = { 0, 0 };
CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
-
+
MGLPolyline *polyLine1 = [MGLPolyline polylineWithCoordinates:coords count:3];
MGLPolyline *polyLine2 = [MGLPolyline polylineWithCoordinates:coords count:3];
-
+
MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[polyLine1, polyLine2]];
-
+
// A GeoJSON feature
NSDictionary *geoJSONFeature = [multiPolylineFeature geoJSONDictionary];
-
+
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"MultiLineString",
@"coordinates": @[@[@[@(coord1.longitude), @(coord1.latitude)],
@@ -257,15 +257,15 @@
CLLocationCoordinate2D coord2 = { 10, 10 };
CLLocationCoordinate2D coord3 = { 0, 0 };
CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
-
+
MGLPolygon *polygon1 = [MGLPolygon polygonWithCoordinates:coords count:3];
MGLPolygon *polygon2 = [MGLPolygon polygonWithCoordinates:coords count:3];
-
+
MGLMultiPolygonFeature *multiPolylineFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[polygon1, polygon2]];
-
+
// A GeoJSON feature
NSDictionary *geoJSONFeature = [multiPolylineFeature geoJSONDictionary];
-
+
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"MultiPolygon",
@"coordinates": @[
@@ -284,10 +284,10 @@
CLLocationCoordinate2D coord3 = { 0, 0 };
CLLocationCoordinate2D coords[] = { coord1, coord2, coord3 };
MGLPointCollectionFeature *pointCollectionFeature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coords count:3];
-
+
// A GeoJSON feature
NSDictionary *geoJSONFeature = [pointCollectionFeature geoJSONDictionary];
-
+
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"MultiPoint",
@"coordinates": @[@[@(coord1.longitude), @(coord1.latitude)],
@@ -301,17 +301,17 @@
MGLPointAnnotation *pointFeature = [[MGLPointAnnotation alloc] init];
CLLocationCoordinate2D pointCoordinate = { 10, 10 };
pointFeature.coordinate = pointCoordinate;
-
+
CLLocationCoordinate2D coord1 = { 0, 0 };
CLLocationCoordinate2D coord2 = { 10, 10 };
CLLocationCoordinate2D coords[] = { coord1, coord2 };
MGLPolyline *polyline = [MGLPolyline polylineWithCoordinates:coords count:2];
-
+
MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[pointFeature,
polyline]];
// A GeoJSON feature
NSDictionary *geoJSONFeature = [shapeCollectionFeature geoJSONDictionary];
-
+
// it has the correct geometry
NSDictionary *expectedGeometry = @{@"type": @"GeometryCollection",
@"geometries": @[
diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm
index 869ad4f9b5..c03b22c399 100644
--- a/platform/darwin/test/MGLFillStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillStyleLayerTests.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -20,13 +20,13 @@
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
-
+
XCTAssertNil(layer.sourceLayerIdentifier);
layer.sourceLayerIdentifier = @"layerID";
XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
layer.sourceLayerIdentifier = nil;
XCTAssertNil(layer.sourceLayerIdentifier);
-
+
XCTAssertNil(layer.predicate);
layer.predicate = [NSPredicate predicateWithValue:NO];
XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
@@ -37,254 +37,343 @@
- (void)testProperties {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::FillLayer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::FillLayer>();
-
+
// fill-antialias
{
XCTAssertTrue(rawLayer->getFillAntialias().isUndefined(),
@"fill-antialias should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillAntialiased;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@NO];
- layer.fillAntialiased = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@NO];
+ layer.fillAntialiased = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { false };
XCTAssertEqual(rawLayer->getFillAntialias(), propertyValue,
@"Setting fillAntialiased to a constant value should update fill-antialias.");
- XCTAssertEqualObjects(layer.fillAntialiased, styleValue,
+ XCTAssertEqualObjects(layer.fillAntialiased, constantStyleValue,
@"fillAntialiased should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillAntialiased = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, false}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillAntialiased = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillAntialias(), propertyValue,
- @"Setting fillAntialiased to a function should update fill-antialias.");
- XCTAssertEqualObjects(layer.fillAntialiased, styleValue,
- @"fillAntialiased should round-trip functions.");
-
+ @"Setting fillAntialiased to a camera function should update fill-antialias.");
+ XCTAssertEqualObjects(layer.fillAntialiased, functionStyleValue,
+ @"fillAntialiased should round-trip camera functions.");
+
+
+
layer.fillAntialiased = nil;
XCTAssertTrue(rawLayer->getFillAntialias().isUndefined(),
@"Unsetting fillAntialiased should return fill-antialias to the default value.");
XCTAssertEqualObjects(layer.fillAntialiased, defaultStyleValue,
@"fillAntialiased should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillAntialiased = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillAntialiased = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// fill-color
{
XCTAssertTrue(rawLayer->getFillColor().isUndefined(),
@"fill-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.fillColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.fillColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.fillColor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
@"Setting fillColor to a constant value should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, styleValue,
+ XCTAssertEqualObjects(layer.fillColor, constantStyleValue,
@"fillColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
- @"Setting fillColor to a function should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, styleValue,
- @"fillColor should round-trip functions.");
-
+ @"Setting fillColor to a camera function should update fill-color.");
+ XCTAssertEqualObjects(layer.fillColor, functionStyleValue,
+ @"fillColor should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.fillColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
+ @"Setting fillColor to a source function should update fill-color.");
+ XCTAssertEqualObjects(layer.fillColor, functionStyleValue,
+ @"fillColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.fillColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
+ @"Setting fillColor to a composite function should update fill-color.");
+ XCTAssertEqualObjects(layer.fillColor, functionStyleValue,
+ @"fillColor should round-trip composite functions.");
+
+
layer.fillColor = nil;
XCTAssertTrue(rawLayer->getFillColor().isUndefined(),
@"Unsetting fillColor should return fill-color to the default value.");
XCTAssertEqualObjects(layer.fillColor, defaultStyleValue,
@"fillColor should return the default value after being unset.");
}
-
+
// fill-opacity
{
XCTAssertTrue(rawLayer->getFillOpacity().isUndefined(),
@"fill-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.fillOpacity = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.fillOpacity = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
@"Setting fillOpacity to a constant value should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, styleValue,
+ XCTAssertEqualObjects(layer.fillOpacity, constantStyleValue,
@"fillOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
- @"Setting fillOpacity to a function should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, styleValue,
- @"fillOpacity should round-trip functions.");
-
+ @"Setting fillOpacity to a camera function should update fill-opacity.");
+ XCTAssertEqualObjects(layer.fillOpacity, functionStyleValue,
+ @"fillOpacity should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.fillOpacity = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
+ @"Setting fillOpacity to a source function should update fill-opacity.");
+ XCTAssertEqualObjects(layer.fillOpacity, functionStyleValue,
+ @"fillOpacity should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.fillOpacity = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
+ @"Setting fillOpacity to a composite function should update fill-opacity.");
+ XCTAssertEqualObjects(layer.fillOpacity, functionStyleValue,
+ @"fillOpacity should round-trip composite functions.");
+
+
layer.fillOpacity = nil;
XCTAssertTrue(rawLayer->getFillOpacity().isUndefined(),
@"Unsetting fillOpacity should return fill-opacity to the default value.");
XCTAssertEqualObjects(layer.fillOpacity, defaultStyleValue,
@"fillOpacity should return the default value after being unset.");
}
-
+
// fill-outline-color
{
XCTAssertTrue(rawLayer->getFillOutlineColor().isUndefined(),
@"fill-outline-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.fillOutlineColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.fillOutlineColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.fillOutlineColor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
@"Setting fillOutlineColor to a constant value should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, styleValue,
+ XCTAssertEqualObjects(layer.fillOutlineColor, constantStyleValue,
@"fillOutlineColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillOutlineColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillOutlineColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
- @"Setting fillOutlineColor to a function should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, styleValue,
- @"fillOutlineColor should round-trip functions.");
-
+ @"Setting fillOutlineColor to a camera function should update fill-outline-color.");
+ XCTAssertEqualObjects(layer.fillOutlineColor, functionStyleValue,
+ @"fillOutlineColor should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.fillOutlineColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
+ @"Setting fillOutlineColor to a source function should update fill-outline-color.");
+ XCTAssertEqualObjects(layer.fillOutlineColor, functionStyleValue,
+ @"fillOutlineColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.fillOutlineColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
+ @"Setting fillOutlineColor to a composite function should update fill-outline-color.");
+ XCTAssertEqualObjects(layer.fillOutlineColor, functionStyleValue,
+ @"fillOutlineColor should round-trip composite functions.");
+
+
layer.fillOutlineColor = nil;
XCTAssertTrue(rawLayer->getFillOutlineColor().isUndefined(),
@"Unsetting fillOutlineColor should return fill-outline-color to the default value.");
XCTAssertEqualObjects(layer.fillOutlineColor, defaultStyleValue,
@"fillOutlineColor should return the default value after being unset.");
}
-
+
// fill-pattern
{
XCTAssertTrue(rawLayer->getFillPattern().isUndefined(),
@"fill-pattern should be unset initially.");
MGLStyleValue<NSString *> *defaultStyleValue = layer.fillPattern;
-
- MGLStyleValue<NSString *> *styleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Fill Pattern"];
- layer.fillPattern = styleValue;
+
+ MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Fill Pattern"];
+ layer.fillPattern = constantStyleValue;
mbgl::style::PropertyValue<std::string> propertyValue = { "Fill Pattern" };
XCTAssertEqual(rawLayer->getFillPattern(), propertyValue,
@"Setting fillPattern to a constant value should update fill-pattern.");
- XCTAssertEqualObjects(layer.fillPattern, styleValue,
+ XCTAssertEqualObjects(layer.fillPattern, constantStyleValue,
@"fillPattern should round-trip constant values.");
+
+ MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillPattern = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Fill Pattern"}} };
+ propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
- styleValue = [MGLStyleValue<NSString *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillPattern = styleValue;
- propertyValue = { mbgl::style::Function<std::string> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillPattern(), propertyValue,
- @"Setting fillPattern to a function should update fill-pattern.");
- XCTAssertEqualObjects(layer.fillPattern, styleValue,
- @"fillPattern should round-trip functions.");
-
+ @"Setting fillPattern to a camera function should update fill-pattern.");
+ XCTAssertEqualObjects(layer.fillPattern, functionStyleValue,
+ @"fillPattern should round-trip camera functions.");
+
+
+
layer.fillPattern = nil;
XCTAssertTrue(rawLayer->getFillPattern().isUndefined(),
@"Unsetting fillPattern should return fill-pattern to the default value.");
XCTAssertEqualObjects(layer.fillPattern, defaultStyleValue,
@"fillPattern should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// fill-translate
{
XCTAssertTrue(rawLayer->getFillTranslate().isUndefined(),
@"fill-translate should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillTranslation;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.fillTranslation = styleValue;
+ layer.fillTranslation = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getFillTranslate(), propertyValue,
@"Setting fillTranslation to a constant value should update fill-translate.");
- XCTAssertEqualObjects(layer.fillTranslation, styleValue,
+ XCTAssertEqualObjects(layer.fillTranslation, constantStyleValue,
@"fillTranslation should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillTranslation = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillTranslation = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillTranslate(), propertyValue,
- @"Setting fillTranslation to a function should update fill-translate.");
- XCTAssertEqualObjects(layer.fillTranslation, styleValue,
- @"fillTranslation should round-trip functions.");
-
+ @"Setting fillTranslation to a camera function should update fill-translate.");
+ XCTAssertEqualObjects(layer.fillTranslation, functionStyleValue,
+ @"fillTranslation should round-trip camera functions.");
+
+
+
layer.fillTranslation = nil;
XCTAssertTrue(rawLayer->getFillTranslate().isUndefined(),
@"Unsetting fillTranslation should return fill-translate to the default value.");
XCTAssertEqualObjects(layer.fillTranslation, defaultStyleValue,
@"fillTranslation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// fill-translate-anchor
{
XCTAssertTrue(rawLayer->getFillTranslateAnchor().isUndefined(),
@"fill-translate-anchor should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillTranslationAnchor;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLFillTranslationAnchor:MGLFillTranslationAnchorViewport]];
- layer.fillTranslationAnchor = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLFillTranslationAnchor:MGLFillTranslationAnchorViewport]];
+ layer.fillTranslationAnchor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getFillTranslateAnchor(), propertyValue,
@"Setting fillTranslationAnchor to a constant value should update fill-translate-anchor.");
- XCTAssertEqualObjects(layer.fillTranslationAnchor, styleValue,
+ XCTAssertEqualObjects(layer.fillTranslationAnchor, constantStyleValue,
@"fillTranslationAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillTranslationAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.fillTranslationAnchor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TranslateAnchorType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getFillTranslateAnchor(), propertyValue,
- @"Setting fillTranslationAnchor to a function should update fill-translate-anchor.");
- XCTAssertEqualObjects(layer.fillTranslationAnchor, styleValue,
- @"fillTranslationAnchor should round-trip functions.");
-
+ @"Setting fillTranslationAnchor to a camera function should update fill-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillTranslationAnchor, functionStyleValue,
+ @"fillTranslationAnchor should round-trip camera functions.");
+
+
+
layer.fillTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getFillTranslateAnchor().isUndefined(),
@"Unsetting fillTranslationAnchor should return fill-translate-anchor to the default value.");
XCTAssertEqualObjects(layer.fillTranslationAnchor, defaultStyleValue,
@"fillTranslationAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}
diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm
index 0dd5efec4d..220a837643 100644
--- a/platform/darwin/test/MGLGeometryTests.mm
+++ b/platform/darwin/test/MGLGeometryTests.mm
@@ -56,20 +56,20 @@
- (void)testGeometryBoxing {
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(38.9131982, -77.0325453144239);
CLLocationCoordinate2D roundTrippedCoordinate = [NSValue valueWithMGLCoordinate:coordinate].MGLCoordinateValue;
-
+
XCTAssertEqual(coordinate.latitude, roundTrippedCoordinate.latitude, @"Latitude should round-trip.");
XCTAssertEqual(coordinate.longitude, roundTrippedCoordinate.longitude, @"Longitude should round-trip.");
-
+
MGLCoordinateSpan span = MGLCoordinateSpanMake(4.383333333333335, -4.299999999999997);
MGLCoordinateSpan roundTrippedSpan = [NSValue valueWithMGLCoordinateSpan:span].MGLCoordinateSpanValue;
-
+
XCTAssertEqual(span.latitudeDelta, roundTrippedSpan.latitudeDelta, @"Latitude delta should round-trip.");
XCTAssertEqual(span.longitudeDelta, roundTrippedSpan.longitudeDelta, @"Longitude delta should round-trip.");
-
+
MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(38.9131982, -77.0325453144239),
CLLocationCoordinate2DMake(37.7757368, -122.4135302));
MGLCoordinateBounds roundTrippedBounds = [NSValue valueWithMGLCoordinateBounds:bounds].MGLCoordinateBoundsValue;
-
+
XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.sw],
[NSValue valueWithMGLCoordinate:roundTrippedBounds.sw],
@"Southwest should round-trip.");
@@ -79,9 +79,9 @@
}
- (void)testCoordinateInCoordinateBounds {
- CLLocationCoordinate2D ne = CLLocationCoordinate2DMake(41, -111);
- CLLocationCoordinate2D sw = CLLocationCoordinate2DMake(45, -104);
- MGLCoordinateBounds wyoming = MGLCoordinateBoundsMake(ne, sw);
+ CLLocationCoordinate2D ne = CLLocationCoordinate2DMake(45, -104);
+ CLLocationCoordinate2D sw = CLLocationCoordinate2DMake(41, -111);
+ MGLCoordinateBounds wyoming = MGLCoordinateBoundsMake(sw, ne);
CLLocationCoordinate2D centerOfWyoming = CLLocationCoordinate2DMake(43, -107.5);
@@ -109,7 +109,7 @@
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];
@@ -121,7 +121,7 @@
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;
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm
index 1abe1cf6c3..95c3e434c0 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.mm
+++ b/platform/darwin/test/MGLLineStyleLayerTests.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -20,13 +20,13 @@
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
-
+
XCTAssertNil(layer.sourceLayerIdentifier);
layer.sourceLayerIdentifier = @"layerID";
XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
layer.sourceLayerIdentifier = nil;
XCTAssertNil(layer.sourceLayerIdentifier);
-
+
XCTAssertNil(layer.predicate);
layer.predicate = [NSPredicate predicateWithValue:NO];
XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
@@ -37,492 +37,652 @@
- (void)testProperties {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGLLineStyleLayer *layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::LineLayer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::LineLayer>();
-
+
// line-cap
{
XCTAssertTrue(rawLayer->getLineCap().isUndefined(),
@"line-cap should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineCap;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapSquare]];
- layer.lineCap = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapSquare]];
+ layer.lineCap = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::LineCapType> propertyValue = { mbgl::style::LineCapType::Square };
XCTAssertEqual(rawLayer->getLineCap(), propertyValue,
@"Setting lineCap to a constant value should update line-cap.");
- XCTAssertEqualObjects(layer.lineCap, styleValue,
+ XCTAssertEqualObjects(layer.lineCap, constantStyleValue,
@"lineCap should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineCap = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::LineCapType> intervalStops = { {{18, mbgl::style::LineCapType::Square}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::LineCapType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineCap = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::LineCapType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineCap(), propertyValue,
- @"Setting lineCap to a function should update line-cap.");
- XCTAssertEqualObjects(layer.lineCap, styleValue,
- @"lineCap should round-trip functions.");
-
+ @"Setting lineCap to a camera function should update line-cap.");
+ XCTAssertEqualObjects(layer.lineCap, functionStyleValue,
+ @"lineCap should round-trip camera functions.");
+
+
+
layer.lineCap = nil;
XCTAssertTrue(rawLayer->getLineCap().isUndefined(),
@"Unsetting lineCap should return line-cap to the default value.");
XCTAssertEqualObjects(layer.lineCap, defaultStyleValue,
@"lineCap should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineCap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineCap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-join
{
XCTAssertTrue(rawLayer->getLineJoin().isUndefined(),
@"line-join should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineJoin;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinMiter]];
- layer.lineJoin = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinMiter]];
+ layer.lineJoin = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::LineJoinType> propertyValue = { mbgl::style::LineJoinType::Miter };
XCTAssertEqual(rawLayer->getLineJoin(), propertyValue,
@"Setting lineJoin to a constant value should update line-join.");
- XCTAssertEqualObjects(layer.lineJoin, styleValue,
+ XCTAssertEqualObjects(layer.lineJoin, constantStyleValue,
@"lineJoin should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineJoin = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::LineJoinType> intervalStops = { {{18, mbgl::style::LineJoinType::Miter}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::LineJoinType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineJoin = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::LineJoinType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineJoin(), propertyValue,
- @"Setting lineJoin to a function should update line-join.");
- XCTAssertEqualObjects(layer.lineJoin, styleValue,
- @"lineJoin should round-trip functions.");
-
+ @"Setting lineJoin to a camera function should update line-join.");
+ XCTAssertEqualObjects(layer.lineJoin, functionStyleValue,
+ @"lineJoin should round-trip camera functions.");
+
+
+
layer.lineJoin = nil;
XCTAssertTrue(rawLayer->getLineJoin().isUndefined(),
@"Unsetting lineJoin should return line-join to the default value.");
XCTAssertEqualObjects(layer.lineJoin, defaultStyleValue,
@"lineJoin should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineJoin = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineJoin = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-miter-limit
{
XCTAssertTrue(rawLayer->getLineMiterLimit().isUndefined(),
@"line-miter-limit should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineMiterLimit;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineMiterLimit = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineMiterLimit = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineMiterLimit(), propertyValue,
@"Setting lineMiterLimit to a constant value should update line-miter-limit.");
- XCTAssertEqualObjects(layer.lineMiterLimit, styleValue,
+ XCTAssertEqualObjects(layer.lineMiterLimit, constantStyleValue,
@"lineMiterLimit should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineMiterLimit = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineMiterLimit = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineMiterLimit(), propertyValue,
- @"Setting lineMiterLimit to a function should update line-miter-limit.");
- XCTAssertEqualObjects(layer.lineMiterLimit, styleValue,
- @"lineMiterLimit should round-trip functions.");
-
+ @"Setting lineMiterLimit to a camera function should update line-miter-limit.");
+ XCTAssertEqualObjects(layer.lineMiterLimit, functionStyleValue,
+ @"lineMiterLimit should round-trip camera functions.");
+
+
+
layer.lineMiterLimit = nil;
XCTAssertTrue(rawLayer->getLineMiterLimit().isUndefined(),
@"Unsetting lineMiterLimit should return line-miter-limit to the default value.");
XCTAssertEqualObjects(layer.lineMiterLimit, defaultStyleValue,
@"lineMiterLimit should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-round-limit
{
XCTAssertTrue(rawLayer->getLineRoundLimit().isUndefined(),
@"line-round-limit should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineRoundLimit;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineRoundLimit = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineRoundLimit = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineRoundLimit(), propertyValue,
@"Setting lineRoundLimit to a constant value should update line-round-limit.");
- XCTAssertEqualObjects(layer.lineRoundLimit, styleValue,
+ XCTAssertEqualObjects(layer.lineRoundLimit, constantStyleValue,
@"lineRoundLimit should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineRoundLimit = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineRoundLimit = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineRoundLimit(), propertyValue,
- @"Setting lineRoundLimit to a function should update line-round-limit.");
- XCTAssertEqualObjects(layer.lineRoundLimit, styleValue,
- @"lineRoundLimit should round-trip functions.");
-
+ @"Setting lineRoundLimit to a camera function should update line-round-limit.");
+ XCTAssertEqualObjects(layer.lineRoundLimit, functionStyleValue,
+ @"lineRoundLimit should round-trip camera functions.");
+
+
+
layer.lineRoundLimit = nil;
XCTAssertTrue(rawLayer->getLineRoundLimit().isUndefined(),
@"Unsetting lineRoundLimit should return line-round-limit to the default value.");
XCTAssertEqualObjects(layer.lineRoundLimit, defaultStyleValue,
@"lineRoundLimit should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-blur
{
XCTAssertTrue(rawLayer->getLineBlur().isUndefined(),
@"line-blur should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineBlur;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineBlur = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineBlur = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
@"Setting lineBlur to a constant value should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, styleValue,
+ XCTAssertEqualObjects(layer.lineBlur, constantStyleValue,
@"lineBlur should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineBlur = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineBlur = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
- @"Setting lineBlur to a function should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, styleValue,
- @"lineBlur should round-trip functions.");
-
+ @"Setting lineBlur to a camera function should update line-blur.");
+ XCTAssertEqualObjects(layer.lineBlur, functionStyleValue,
+ @"lineBlur should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.lineBlur = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
+ @"Setting lineBlur to a source function should update line-blur.");
+ XCTAssertEqualObjects(layer.lineBlur, functionStyleValue,
+ @"lineBlur should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.lineBlur = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
+ @"Setting lineBlur to a composite function should update line-blur.");
+ XCTAssertEqualObjects(layer.lineBlur, functionStyleValue,
+ @"lineBlur should round-trip composite functions.");
+
+
layer.lineBlur = nil;
XCTAssertTrue(rawLayer->getLineBlur().isUndefined(),
@"Unsetting lineBlur should return line-blur to the default value.");
XCTAssertEqualObjects(layer.lineBlur, defaultStyleValue,
@"lineBlur should return the default value after being unset.");
}
-
+
// line-color
{
XCTAssertTrue(rawLayer->getLineColor().isUndefined(),
@"line-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.lineColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.lineColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.lineColor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
@"Setting lineColor to a constant value should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, styleValue,
+ XCTAssertEqualObjects(layer.lineColor, constantStyleValue,
@"lineColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
- @"Setting lineColor to a function should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, styleValue,
- @"lineColor should round-trip functions.");
-
+ @"Setting lineColor to a camera function should update line-color.");
+ XCTAssertEqualObjects(layer.lineColor, functionStyleValue,
+ @"lineColor should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.lineColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
+ @"Setting lineColor to a source function should update line-color.");
+ XCTAssertEqualObjects(layer.lineColor, functionStyleValue,
+ @"lineColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.lineColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
+ @"Setting lineColor to a composite function should update line-color.");
+ XCTAssertEqualObjects(layer.lineColor, functionStyleValue,
+ @"lineColor should round-trip composite functions.");
+
+
layer.lineColor = nil;
XCTAssertTrue(rawLayer->getLineColor().isUndefined(),
@"Unsetting lineColor should return line-color to the default value.");
XCTAssertEqualObjects(layer.lineColor, defaultStyleValue,
@"lineColor should return the default value after being unset.");
}
-
+
// line-dasharray
{
XCTAssertTrue(rawLayer->getLineDasharray().isUndefined(),
@"line-dasharray should be unset initially.");
MGLStyleValue<NSArray<NSNumber *> *> *defaultStyleValue = layer.lineDashPattern;
-
- MGLStyleValue<NSArray<NSNumber *> *> *styleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithRawValue:@[@1, @2]];
- layer.lineDashPattern = styleValue;
+
+ MGLStyleValue<NSArray<NSNumber *> *> *constantStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithRawValue:@[@1, @2]];
+ layer.lineDashPattern = constantStyleValue;
mbgl::style::PropertyValue<std::vector<float>> propertyValue = { {1, 2} };
XCTAssertEqual(rawLayer->getLineDasharray(), propertyValue,
@"Setting lineDashPattern to a constant value should update line-dasharray.");
- XCTAssertEqualObjects(layer.lineDashPattern, styleValue,
+ XCTAssertEqualObjects(layer.lineDashPattern, constantStyleValue,
@"lineDashPattern should round-trip constant values.");
+
+ MGLStyleValue<NSArray<NSNumber *> *> * functionStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineDashPattern = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::vector<float>> intervalStops = { {{18, {1, 2}}} };
+ propertyValue = mbgl::style::CameraFunction<std::vector<float>> { intervalStops };
- styleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineDashPattern = styleValue;
- propertyValue = { mbgl::style::Function<std::vector<float>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineDasharray(), propertyValue,
- @"Setting lineDashPattern to a function should update line-dasharray.");
- XCTAssertEqualObjects(layer.lineDashPattern, styleValue,
- @"lineDashPattern should round-trip functions.");
-
+ @"Setting lineDashPattern to a camera function should update line-dasharray.");
+ XCTAssertEqualObjects(layer.lineDashPattern, functionStyleValue,
+ @"lineDashPattern should round-trip camera functions.");
+
+
+
layer.lineDashPattern = nil;
XCTAssertTrue(rawLayer->getLineDasharray().isUndefined(),
@"Unsetting lineDashPattern should return line-dasharray to the default value.");
XCTAssertEqualObjects(layer.lineDashPattern, defaultStyleValue,
@"lineDashPattern should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSArray<NSNumber *> *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-gap-width
{
XCTAssertTrue(rawLayer->getLineGapWidth().isUndefined(),
@"line-gap-width should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineGapWidth;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineGapWidth = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineGapWidth = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
@"Setting lineGapWidth to a constant value should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, styleValue,
+ XCTAssertEqualObjects(layer.lineGapWidth, constantStyleValue,
@"lineGapWidth should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineGapWidth = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineGapWidth = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
- @"Setting lineGapWidth to a function should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, styleValue,
- @"lineGapWidth should round-trip functions.");
-
+ @"Setting lineGapWidth to a camera function should update line-gap-width.");
+ XCTAssertEqualObjects(layer.lineGapWidth, functionStyleValue,
+ @"lineGapWidth should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.lineGapWidth = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
+ @"Setting lineGapWidth to a source function should update line-gap-width.");
+ XCTAssertEqualObjects(layer.lineGapWidth, functionStyleValue,
+ @"lineGapWidth should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.lineGapWidth = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
+ @"Setting lineGapWidth to a composite function should update line-gap-width.");
+ XCTAssertEqualObjects(layer.lineGapWidth, functionStyleValue,
+ @"lineGapWidth should round-trip composite functions.");
+
+
layer.lineGapWidth = nil;
XCTAssertTrue(rawLayer->getLineGapWidth().isUndefined(),
@"Unsetting lineGapWidth should return line-gap-width to the default value.");
XCTAssertEqualObjects(layer.lineGapWidth, defaultStyleValue,
@"lineGapWidth should return the default value after being unset.");
}
-
+
// line-offset
{
XCTAssertTrue(rawLayer->getLineOffset().isUndefined(),
@"line-offset should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineOffset;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineOffset = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineOffset = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
@"Setting lineOffset to a constant value should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, styleValue,
+ XCTAssertEqualObjects(layer.lineOffset, constantStyleValue,
@"lineOffset should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineOffset = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineOffset = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
- @"Setting lineOffset to a function should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, styleValue,
- @"lineOffset should round-trip functions.");
-
+ @"Setting lineOffset to a camera function should update line-offset.");
+ XCTAssertEqualObjects(layer.lineOffset, functionStyleValue,
+ @"lineOffset should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.lineOffset = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
+ @"Setting lineOffset to a source function should update line-offset.");
+ XCTAssertEqualObjects(layer.lineOffset, functionStyleValue,
+ @"lineOffset should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.lineOffset = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
+ @"Setting lineOffset to a composite function should update line-offset.");
+ XCTAssertEqualObjects(layer.lineOffset, functionStyleValue,
+ @"lineOffset should round-trip composite functions.");
+
+
layer.lineOffset = nil;
XCTAssertTrue(rawLayer->getLineOffset().isUndefined(),
@"Unsetting lineOffset should return line-offset to the default value.");
XCTAssertEqualObjects(layer.lineOffset, defaultStyleValue,
@"lineOffset should return the default value after being unset.");
}
-
+
// line-opacity
{
XCTAssertTrue(rawLayer->getLineOpacity().isUndefined(),
@"line-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineOpacity = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineOpacity = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
@"Setting lineOpacity to a constant value should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, styleValue,
+ XCTAssertEqualObjects(layer.lineOpacity, constantStyleValue,
@"lineOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
- @"Setting lineOpacity to a function should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, styleValue,
- @"lineOpacity should round-trip functions.");
-
+ @"Setting lineOpacity to a camera function should update line-opacity.");
+ XCTAssertEqualObjects(layer.lineOpacity, functionStyleValue,
+ @"lineOpacity should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.lineOpacity = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
+ @"Setting lineOpacity to a source function should update line-opacity.");
+ XCTAssertEqualObjects(layer.lineOpacity, functionStyleValue,
+ @"lineOpacity should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.lineOpacity = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
+ @"Setting lineOpacity to a composite function should update line-opacity.");
+ XCTAssertEqualObjects(layer.lineOpacity, functionStyleValue,
+ @"lineOpacity should round-trip composite functions.");
+
+
layer.lineOpacity = nil;
XCTAssertTrue(rawLayer->getLineOpacity().isUndefined(),
@"Unsetting lineOpacity should return line-opacity to the default value.");
XCTAssertEqualObjects(layer.lineOpacity, defaultStyleValue,
@"lineOpacity should return the default value after being unset.");
}
-
+
// line-pattern
{
XCTAssertTrue(rawLayer->getLinePattern().isUndefined(),
@"line-pattern should be unset initially.");
MGLStyleValue<NSString *> *defaultStyleValue = layer.linePattern;
-
- MGLStyleValue<NSString *> *styleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Line Pattern"];
- layer.linePattern = styleValue;
+
+ MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Line Pattern"];
+ layer.linePattern = constantStyleValue;
mbgl::style::PropertyValue<std::string> propertyValue = { "Line Pattern" };
XCTAssertEqual(rawLayer->getLinePattern(), propertyValue,
@"Setting linePattern to a constant value should update line-pattern.");
- XCTAssertEqualObjects(layer.linePattern, styleValue,
+ XCTAssertEqualObjects(layer.linePattern, constantStyleValue,
@"linePattern should round-trip constant values.");
+
+ MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.linePattern = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Line Pattern"}} };
+ propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
- styleValue = [MGLStyleValue<NSString *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.linePattern = styleValue;
- propertyValue = { mbgl::style::Function<std::string> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLinePattern(), propertyValue,
- @"Setting linePattern to a function should update line-pattern.");
- XCTAssertEqualObjects(layer.linePattern, styleValue,
- @"linePattern should round-trip functions.");
-
+ @"Setting linePattern to a camera function should update line-pattern.");
+ XCTAssertEqualObjects(layer.linePattern, functionStyleValue,
+ @"linePattern should round-trip camera functions.");
+
+
+
layer.linePattern = nil;
XCTAssertTrue(rawLayer->getLinePattern().isUndefined(),
@"Unsetting linePattern should return line-pattern to the default value.");
XCTAssertEqualObjects(layer.linePattern, defaultStyleValue,
@"linePattern should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.linePattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.linePattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-translate
{
XCTAssertTrue(rawLayer->getLineTranslate().isUndefined(),
@"line-translate should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineTranslation;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.lineTranslation = styleValue;
+ layer.lineTranslation = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getLineTranslate(), propertyValue,
@"Setting lineTranslation to a constant value should update line-translate.");
- XCTAssertEqualObjects(layer.lineTranslation, styleValue,
+ XCTAssertEqualObjects(layer.lineTranslation, constantStyleValue,
@"lineTranslation should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineTranslation = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineTranslation = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineTranslate(), propertyValue,
- @"Setting lineTranslation to a function should update line-translate.");
- XCTAssertEqualObjects(layer.lineTranslation, styleValue,
- @"lineTranslation should round-trip functions.");
-
+ @"Setting lineTranslation to a camera function should update line-translate.");
+ XCTAssertEqualObjects(layer.lineTranslation, functionStyleValue,
+ @"lineTranslation should round-trip camera functions.");
+
+
+
layer.lineTranslation = nil;
XCTAssertTrue(rawLayer->getLineTranslate().isUndefined(),
@"Unsetting lineTranslation should return line-translate to the default value.");
XCTAssertEqualObjects(layer.lineTranslation, defaultStyleValue,
@"lineTranslation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-translate-anchor
{
XCTAssertTrue(rawLayer->getLineTranslateAnchor().isUndefined(),
@"line-translate-anchor should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.lineTranslationAnchor;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineTranslationAnchor:MGLLineTranslationAnchorViewport]];
- layer.lineTranslationAnchor = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLineTranslationAnchor:MGLLineTranslationAnchorViewport]];
+ layer.lineTranslationAnchor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getLineTranslateAnchor(), propertyValue,
@"Setting lineTranslationAnchor to a constant value should update line-translate-anchor.");
- XCTAssertEqualObjects(layer.lineTranslationAnchor, styleValue,
+ XCTAssertEqualObjects(layer.lineTranslationAnchor, constantStyleValue,
@"lineTranslationAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineTranslationAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineTranslationAnchor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TranslateAnchorType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineTranslateAnchor(), propertyValue,
- @"Setting lineTranslationAnchor to a function should update line-translate-anchor.");
- XCTAssertEqualObjects(layer.lineTranslationAnchor, styleValue,
- @"lineTranslationAnchor should round-trip functions.");
-
+ @"Setting lineTranslationAnchor to a camera function should update line-translate-anchor.");
+ XCTAssertEqualObjects(layer.lineTranslationAnchor, functionStyleValue,
+ @"lineTranslationAnchor should round-trip camera functions.");
+
+
+
layer.lineTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getLineTranslateAnchor().isUndefined(),
@"Unsetting lineTranslationAnchor should return line-translate-anchor to the default value.");
XCTAssertEqualObjects(layer.lineTranslationAnchor, defaultStyleValue,
@"lineTranslationAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// line-width
{
XCTAssertTrue(rawLayer->getLineWidth().isUndefined(),
@"line-width should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.lineWidth;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.lineWidth = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.lineWidth = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
@"Setting lineWidth to a constant value should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, styleValue,
+ XCTAssertEqualObjects(layer.lineWidth, constantStyleValue,
@"lineWidth should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.lineWidth = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.lineWidth = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
- @"Setting lineWidth to a function should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, styleValue,
- @"lineWidth should round-trip functions.");
-
+ @"Setting lineWidth to a camera function should update line-width.");
+ XCTAssertEqualObjects(layer.lineWidth, functionStyleValue,
+ @"lineWidth should round-trip camera functions.");
+
+
+
layer.lineWidth = nil;
XCTAssertTrue(rawLayer->getLineWidth().isUndefined(),
@"Unsetting lineWidth should return line-width to the default value.");
XCTAssertEqualObjects(layer.lineWidth, defaultStyleValue,
@"lineWidth should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.lineWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}
diff --git a/platform/darwin/test/MGLNSStringAdditionsTests.m b/platform/darwin/test/MGLNSStringAdditionsTests.m
index 0c8a9f8143..f07f2c1423 100644
--- a/platform/darwin/test/MGLNSStringAdditionsTests.m
+++ b/platform/darwin/test/MGLNSStringAdditionsTests.m
@@ -10,31 +10,31 @@
- (void)testTitleCasedString {
NSLocale *locale = [NSLocale currentLocale];
-
+
XCTAssertEqualObjects([@"© OpenStreetMap" mgl_titleCasedStringWithLocale:locale], @"© OpenStreetMap");
XCTAssertEqualObjects([@"© OSM" mgl_titleCasedStringWithLocale:locale], @"© OSM");
-
+
XCTAssertEqualObjects([@"Improve this map" mgl_titleCasedStringWithLocale:locale], @"Improve This Map");
XCTAssertEqualObjects([@"Improve This Map" mgl_titleCasedStringWithLocale:locale], @"Improve This Map");
-
+
XCTAssertEqualObjects([@"Improve the map" mgl_titleCasedStringWithLocale:locale], @"Improve the Map");
XCTAssertEqualObjects([@"Improve The Map" mgl_titleCasedStringWithLocale:locale], @"Improve The Map");
-
+
XCTAssertEqualObjects([@"Improve a map" mgl_titleCasedStringWithLocale:locale], @"Improve a Map");
XCTAssertEqualObjects([@"Improve A Map" mgl_titleCasedStringWithLocale:locale], @"Improve A Map");
-
+
XCTAssertEqualObjects([@"Improve for the map" mgl_titleCasedStringWithLocale:locale], @"Improve for the Map");
XCTAssertEqualObjects([@"Improve For The Map" mgl_titleCasedStringWithLocale:locale], @"Improve For The Map");
-
+
XCTAssertEqualObjects([@"Improve and map" mgl_titleCasedStringWithLocale:locale], @"Improve and Map");
XCTAssertEqualObjects([@"Improve And Map" mgl_titleCasedStringWithLocale:locale], @"Improve And Map");
-
+
XCTAssertEqualObjects([@"Improve while mapping" mgl_titleCasedStringWithLocale:locale], @"Improve While Mapping");
XCTAssertEqualObjects([@"Improve While Mapping" mgl_titleCasedStringWithLocale:locale], @"Improve While Mapping");
-
+
XCTAssertEqualObjects([@"Improve with the map" mgl_titleCasedStringWithLocale:locale], @"Improve With the Map");
XCTAssertEqualObjects([@"Improve With The Map" mgl_titleCasedStringWithLocale:locale], @"Improve With The Map");
-
+
XCTAssertEqualObjects([@"Improve this iPhone" mgl_titleCasedStringWithLocale:locale], @"Improve This iPhone");
XCTAssertEqualObjects([@"Improve This iPhone" mgl_titleCasedStringWithLocale:locale], @"Improve This iPhone");
}
diff --git a/platform/darwin/test/MGLOfflinePackTests.m b/platform/darwin/test/MGLOfflinePackTests.m
index fa231ba005..f58f306e5d 100644
--- a/platform/darwin/test/MGLOfflinePackTests.m
+++ b/platform/darwin/test/MGLOfflinePackTests.m
@@ -9,9 +9,9 @@
- (void)testInvalidation {
MGLOfflinePack *invalidPack = [[MGLOfflinePack alloc] init];
-
+
XCTAssertEqual(invalidPack.state, MGLOfflinePackStateInvalid, @"Offline pack should be invalid when initialized independently of MGLOfflineStorage.");
-
+
XCTAssertThrowsSpecificNamed(invalidPack.region, NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when accessing its region.");
XCTAssertThrowsSpecificNamed(invalidPack.context, NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when accessing its context.");
XCTAssertThrowsSpecificNamed([invalidPack resume], NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when being resumed.");
@@ -28,7 +28,7 @@
.maximumResourcesExpected = UINT64_MAX,
};
MGLOfflinePackProgress roundTrippedProgress = [NSValue valueWithMGLOfflinePackProgress:progress].MGLOfflinePackProgressValue;
-
+
XCTAssertEqual(progress.countOfResourcesCompleted, roundTrippedProgress.countOfResourcesCompleted, @"Completed resources should round-trip.");
XCTAssertEqual(progress.countOfResourcesExpected, roundTrippedProgress.countOfResourcesExpected, @"Expected resources should round-trip.");
XCTAssertEqual(progress.countOfBytesCompleted, roundTrippedProgress.countOfBytesCompleted, @"Completed bytes should round-trip.");
diff --git a/platform/darwin/test/MGLOfflineRegionTests.m b/platform/darwin/test/MGLOfflineRegionTests.m
index bb467dd35b..ff079fe798 100644
--- a/platform/darwin/test/MGLOfflineRegionTests.m
+++ b/platform/darwin/test/MGLOfflineRegionTests.m
@@ -12,7 +12,7 @@
MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(kCLLocationCoordinate2DInvalid, kCLLocationCoordinate2DInvalid);
MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:nil bounds:bounds fromZoomLevel:0 toZoomLevel:DBL_MAX];
XCTAssertEqualObjects(region.styleURL, [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion], @"Streets isn’t the default style.");
-
+
NSURL *localURL = [NSURL URLWithString:@"beautiful.style"];
XCTAssertThrowsSpecificNamed([[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:localURL bounds:bounds fromZoomLevel:0 toZoomLevel:DBL_MAX], NSException, @"Invalid style URL", @"No exception raised when initializing region with a local file URL as the style URL.");
}
@@ -22,7 +22,7 @@
MGLTilePyramidOfflineRegion *original = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:[MGLStyle lightStyleURLWithVersion:MGLStyleDefaultVersion] bounds:bounds fromZoomLevel:5 toZoomLevel:10];
MGLTilePyramidOfflineRegion *copy = [original copy];
XCTAssertEqualObjects(original, copy, @"Tile pyramid region should be equal to its copy.");
-
+
XCTAssertEqualObjects(original.styleURL, copy.styleURL, @"Style URL has changed.");
XCTAssert(MGLCoordinateBoundsEqualToCoordinateBounds(original.bounds, copy.bounds), @"Bounds have changed.");
XCTAssertEqual(original.minimumZoomLevel, original.minimumZoomLevel, @"Minimum zoom level has changed.");
diff --git a/platform/darwin/test/MGLOfflineStorageTests.m b/platform/darwin/test/MGLOfflineStorageTests.mm
index 07540b5645..28c6633028 100644
--- a/platform/darwin/test/MGLOfflineStorageTests.m
+++ b/platform/darwin/test/MGLOfflineStorageTests.mm
@@ -1,8 +1,12 @@
#import <Mapbox/Mapbox.h>
+#import "MGLOfflineStorage_Private.h"
+
#import <XCTest/XCTest.h>
-@interface MGLOfflineStorageTests : XCTestCase
+#include <mbgl/util/run_loop.hpp>
+
+@interface MGLOfflineStorageTests : XCTestCase <MGLOfflineStorageDelegate>
@end
@@ -10,12 +14,12 @@
- (void)setUp {
[super setUp];
-
+
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
XCTestExpectation *expectation = [self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) {
- NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue];
- return changeKind = NSKeyValueChangeSetting;
+ const auto changeKind = static_cast<NSKeyValueChange>([change[NSKeyValueChangeKindKey] unsignedLongValue]);
+ return changeKind == NSKeyValueChangeSetting;
}];
if ([MGLOfflineStorage sharedOfflineStorage].packs) {
[expectation fulfill];
@@ -23,7 +27,7 @@
} else {
[self waitForExpectationsWithTimeout:2 handler:nil];
}
-
+
XCTAssertNotNil([MGLOfflineStorage sharedOfflineStorage].packs, @"Shared offline storage object should have a non-nil collection of packs by this point.");
});
}
@@ -34,7 +38,7 @@
- (void)testAddPack {
NSUInteger countOfPacks = [MGLOfflineStorage sharedOfflineStorage].packs.count;
-
+
NSURL *styleURL = [MGLStyle lightStyleURLWithVersion:8];
/// Somewhere near Grape Grove, Ohio, United States.
MGLCoordinateBounds bounds = {
@@ -43,17 +47,17 @@
};
double zoomLevel = 20;
MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:styleURL bounds:bounds fromZoomLevel:zoomLevel toZoomLevel:zoomLevel];
-
+
NSString *nameKey = @"Name";
NSString *name = @"🍇 Grape Grove";
-
+
NSData *context = [NSKeyedArchiver archivedDataWithRootObject:@{
nameKey: name,
}];
-
+
__block MGLOfflinePack *pack;
[self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) {
- NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue];
+ const auto changeKind = static_cast<NSKeyValueChange>([change[NSKeyValueChangeKindKey] unsignedLongValue]);
NSIndexSet *indices = change[NSKeyValueChangeIndexesKey];
return changeKind == NSKeyValueChangeInsertion && indices.count == 1;
}];
@@ -65,40 +69,40 @@
[additionCompletionHandlerExpectation fulfill];
}];
[self waitForExpectationsWithTimeout:2 handler:nil];
-
+
XCTAssertEqual([MGLOfflineStorage sharedOfflineStorage].packs.count, countOfPacks + 1, @"Added pack should have been added to the canonical collection of packs owned by the shared offline storage object. This assertion can fail if this test is run before -testAAALoadPacks.");
-
+
XCTAssertEqual(pack, [MGLOfflineStorage sharedOfflineStorage].packs.lastObject, @"Pack should be appended to end of packs array.");
-
+
XCTAssertEqualObjects(pack.region, region, @"Added pack’s region has changed.");
-
+
NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context];
XCTAssert([userInfo isKindOfClass:[NSDictionary class]], @"Context of offline pack isn’t a dictionary.");
XCTAssert([userInfo[nameKey] isKindOfClass:[NSString class]], @"Name of offline pack isn’t a string.");
XCTAssertEqualObjects(userInfo[nameKey], name, @"Name of offline pack has changed.");
-
+
XCTAssertEqual(pack.state, MGLOfflinePackStateInactive, @"New pack should initially have inactive state.");
-
+
[self keyValueObservingExpectationForObject:pack keyPath:@"state" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) {
- NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue];
- MGLOfflinePackState state = [change[NSKeyValueChangeNewKey] integerValue];
+ const auto changeKind = static_cast<NSKeyValueChange>([change[NSKeyValueChangeKindKey] unsignedLongValue]);
+ const auto state = static_cast<MGLOfflinePackState>([change[NSKeyValueChangeNewKey] longValue]);
return changeKind == NSKeyValueChangeSetting && state == MGLOfflinePackStateInactive;
}];
[self expectationForNotification:MGLOfflinePackProgressChangedNotification object:pack handler:^BOOL(NSNotification * _Nonnull notification) {
MGLOfflinePack *notificationPack = notification.object;
XCTAssert([notificationPack isKindOfClass:[MGLOfflinePack class]], @"Object of notification should be an MGLOfflinePack.");
-
+
NSDictionary *userInfo = notification.userInfo;
XCTAssertNotNil(userInfo, @"Progress change notification should have a userInfo dictionary.");
-
+
NSNumber *stateNumber = userInfo[MGLOfflinePackUserInfoKeyState];
XCTAssert([stateNumber isKindOfClass:[NSNumber class]], @"Progress change notification’s state should be an NSNumber.");
XCTAssertEqual(stateNumber.integerValue, pack.state, @"State in a progress change notification should match the pack’s state.");
-
+
NSValue *progressValue = userInfo[MGLOfflinePackUserInfoKeyProgress];
XCTAssert([progressValue isKindOfClass:[NSValue class]], @"Progress change notification’s progress should be an NSValue.");
XCTAssertEqualObjects(progressValue, [NSValue valueWithMGLOfflinePackProgress:pack.progress], @"Progress change notification’s progress should match pack’s progress.");
-
+
return notificationPack == pack && pack.state == MGLOfflinePackStateInactive;
}];
[pack requestProgress];
@@ -131,14 +135,14 @@
- (void)testRemovePack {
NSUInteger countOfPacks = [MGLOfflineStorage sharedOfflineStorage].packs.count;
-
+
MGLOfflinePack *pack = [MGLOfflineStorage sharedOfflineStorage].packs.lastObject;
XCTAssertNotNil(pack, @"Added pack should still exist.");
-
+
[self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) {
- NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue];
+ const auto changeKind = static_cast<NSKeyValueChange>([change[NSKeyValueChangeKindKey] unsignedLongValue]);
NSIndexSet *indices = change[NSKeyValueChangeIndexesKey];
- return changeKind = NSKeyValueChangeRemoval && indices.count == 1;
+ return changeKind == NSKeyValueChangeRemoval && indices.count == 1;
}];
XCTestExpectation *completionHandlerExpectation = [self expectationWithDescription:@"remove pack completion handler"];
[[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:^(NSError * _Nullable error) {
@@ -146,9 +150,9 @@
[completionHandlerExpectation fulfill];
}];
[self waitForExpectationsWithTimeout:1 handler:nil];
-
+
XCTAssertEqual(pack.state, MGLOfflinePackStateInvalid, @"Removed pack should have been invalidated synchronously.");
-
+
XCTAssertEqual([MGLOfflineStorage sharedOfflineStorage].packs.count, countOfPacks - 1, @"Removed pack should have been removed from the canonical collection of packs owned by the shared offline storage object. This assertion can fail if this test is run before -testAAALoadPacks or -testAddPack.");
}
@@ -156,4 +160,36 @@
XCTAssertGreaterThan([MGLOfflineStorage sharedOfflineStorage].countOfBytesCompleted, 0);
}
+- (NSURL *)offlineStorage:(MGLOfflineStorage *)storage
+ URLForResourceOfKind:(MGLResourceKind)kind
+ withURL:(NSURL *)url {
+ if ([url.scheme isEqual: @"test"] && [url.host isEqual: @"api"]) {
+ return [NSURL URLWithString:@"https://api.mapbox.com"];
+ } else {
+ return url;
+ }
+}
+
+- (void)testResourceTransform {
+ MGLOfflineStorage *os = [MGLOfflineStorage sharedOfflineStorage];
+ [os setDelegate:self];
+
+ auto fs = os.mbglFileSource;
+
+ // Delegate returns "https://api.mapbox.com" as a replacement URL.
+ const mbgl::Resource resource { mbgl::Resource::Unknown, "test://api" };
+ std::unique_ptr<mbgl::AsyncRequest> req;
+ req = fs->request(resource, [&](mbgl::Response res) {
+ req.reset();
+ XCTAssertFalse(res.error.get(), @"Request should not return an error");
+ XCTAssertTrue(res.data.get(), @"Request should return data");
+ XCTAssertEqual("{\"api\":\"mapbox\"}", *res.data, @"Request did not return expected data");
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ });
+
+ CFRunLoopRun();
+
+ [os setDelegate:nil];
+}
+
@end
diff --git a/platform/darwin/test/MGLPredicateTests.mm b/platform/darwin/test/MGLPredicateTests.mm
index fbd144d28a..6e6951dcdd 100644
--- a/platform/darwin/test/MGLPredicateTests.mm
+++ b/platform/darwin/test/MGLPredicateTests.mm
@@ -29,13 +29,13 @@ namespace mbgl {
mbgl::style::AllFilter expected;
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithValue:NO].mgl_filter;
mbgl::style::AnyFilter expected;
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a = 'b'"].mgl_filter;
mbgl::style::EqualsFilter expected = { .key = "a", .value = std::string("b") };
@@ -43,47 +43,83 @@ namespace mbgl {
}
{
+ auto actual = [NSPredicate predicateWithFormat:@"%K = 'Point'", @"$type"].mgl_filter;
+ mbgl::style::TypeEqualsFilter expected = { .value = mbgl::FeatureType::Point };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K = 67086180", @"$id"].mgl_filter;
+ mbgl::style::IdentifierEqualsFilter expected = { .value = UINT64_C(67086180) };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K = nil", @"$id"].mgl_filter;
+ mbgl::style::NotHasIdentifierFilter expected;
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
auto actual = [NSPredicate predicateWithFormat:@"a = nil"].mgl_filter;
mbgl::style::NotHasFilter expected = { .key = "a" };
MGLAssertEqualFilters(actual, expected);
}
{
+ auto actual = [NSPredicate predicateWithFormat:@"%K != 'Point'", @"$type"].mgl_filter;
+ mbgl::style::TypeNotEqualsFilter expected = { .value = mbgl::FeatureType::Point };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K != 67086180", @"$id"].mgl_filter;
+ mbgl::style::IdentifierNotEqualsFilter expected = { .value = UINT64_C(67086180) };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K != nil", @"$id"].mgl_filter;
+ mbgl::style::HasIdentifierFilter expected;
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
auto actual = [NSPredicate predicateWithFormat:@"a != 'b'"].mgl_filter;
mbgl::style::NotEqualsFilter expected = { .key = "a", .value = std::string("b") };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a != nil"].mgl_filter;
mbgl::style::HasFilter expected = { .key = "a" };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a < 'b'"].mgl_filter;
mbgl::style::LessThanFilter expected = { .key = "a", .value = std::string("b") };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a <= 'b'"].mgl_filter;
mbgl::style::LessThanEqualsFilter expected = { .key = "a", .value = std::string("b") };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a > 'b'"].mgl_filter;
mbgl::style::GreaterThanFilter expected = { .key = "a", .value = std::string("b") };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a >= 'b'"].mgl_filter;
mbgl::style::GreaterThanEqualsFilter expected = { .key = "a", .value = std::string("b") };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"].mgl_filter;
mbgl::style::AllFilter expected = {
@@ -94,7 +130,7 @@ namespace mbgl {
};
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@"b", @"z"]].mgl_filter;
mbgl::style::AllFilter expected = {
@@ -105,36 +141,78 @@ namespace mbgl {
};
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].mgl_filter;
mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a IN %@", @[@"b", @"c"]].mgl_filter;
mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"'Mapbox' IN a"].mgl_filter, NSException, NSInvalidArgumentException);
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K IN {'LineString', 'Polygon'}", @"$type"].mgl_filter;
+ mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K IN %@", @"$type", @[@"LineString", @"Polygon"]].mgl_filter;
+ mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"].mgl_filter;
+ mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
+ MGLAssertEqualFilters(actual, expected);
+ }
{
+ auto actual = [NSPredicate predicateWithFormat:@"%K IN %@", @"$id", @[@67086180, @3709678893, @3352016856, @4189833989]].mgl_filter;
+ mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"'Mapbox' IN a"].mgl_filter, NSException, NSInvalidArgumentException);
+
+ {
auto actual = [NSPredicate predicateWithFormat:@"{'b', 'c'} CONTAINS a"].mgl_filter;
mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@"b", @"c"]].mgl_filter;
mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a CONTAINS 'Mapbox'"].mgl_filter, NSException, NSInvalidArgumentException);
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS %K", @[@"LineString", @"Polygon"], @"$type"].mgl_filter;
+ mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ {
+ auto actual = [NSPredicate predicateWithFormat:@"{67086180, 3709678893, 3352016856, 4189833989} CONTAINS %K", @"$id"].mgl_filter;
+ mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
+ MGLAssertEqualFilters(actual, expected);
+ }
{
+ auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS %K", @[@67086180, @3709678893, @3352016856, @4189833989], @"$id"].mgl_filter;
+ mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
+ MGLAssertEqualFilters(actual, expected);
+ }
+
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a CONTAINS 'Mapbox'"].mgl_filter, NSException, NSInvalidArgumentException);
+
+ {
auto actual = [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"].mgl_filter;
mbgl::style::AllFilter expected = {
.filters = {
@@ -144,7 +222,7 @@ namespace mbgl {
};
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"].mgl_filter;
mbgl::style::AnyFilter expected = {
@@ -155,7 +233,7 @@ namespace mbgl {
};
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' AND c == 'd')"].mgl_filter;
mbgl::style::NoneFilter expected = {
@@ -170,7 +248,7 @@ namespace mbgl {
};
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"].mgl_filter;
mbgl::style::NoneFilter expected = {
@@ -181,50 +259,50 @@ namespace mbgl {
};
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT a == nil"].mgl_filter;
mbgl::style::HasFilter expected = { .key = "a" };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT a != nil"].mgl_filter;
mbgl::style::NotHasFilter expected = { .key = "a" };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].mgl_filter;
mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT a IN %@", @[@"b", @"c"]].mgl_filter;
mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT {'b', 'c'} CONTAINS a"].mgl_filter;
mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
-
+
{
auto actual = [NSPredicate predicateWithFormat:@"NOT %@ CONTAINS a", @[@"b", @"c"]].mgl_filter;
mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
MGLAssertEqualFilters(actual, expected);
}
-
+
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BEGINSWITH 'L'"].mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a ENDSWITH 'itude'"].mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a LIKE 'glob?trotter'"].mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a MATCHES 'i\\w{18}n'"].mgl_filter, NSException, NSInvalidArgumentException);
NSPredicate *selectorPredicate = [NSPredicate predicateWithFormat:@"(SELF isKindOfClass: %@)", [MGLPolyline class]];
XCTAssertThrowsSpecificNamed(selectorPredicate.mgl_filter, NSException, NSInvalidArgumentException);
-
+
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings) {
XCTAssertTrue(NO, @"Predicate block should not be evaluated.");
return NO;
@@ -233,47 +311,100 @@ namespace mbgl {
- (void)testPredication {
XCTAssertNil([NSPredicate mgl_predicateWithFilter:mbgl::style::NullFilter()]);
-
+
{
mbgl::style::EqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = 'b'"]);
}
{
+ mbgl::style::TypeEqualsFilter filter = { .value = mbgl::FeatureType::Point };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K = 'Point'", @"$type"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::TypeEqualsFilter filter = { .value = mbgl::FeatureType::LineString };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K = 'LineString'", @"$type"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::TypeEqualsFilter filter = { .value = mbgl::FeatureType::Polygon };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K = 'Polygon'", @"$type"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::IdentifierEqualsFilter filter = { .value = UINT64_C(67086180) };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K = 67086180", @"$id"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::NotHasIdentifierFilter filter;
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K = nil", @"$id"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::TypeEqualsFilter filter = { .value = mbgl::FeatureType::Unknown };
+ XCTAssertThrowsSpecificNamed([NSPredicate mgl_predicateWithFilter:filter], NSException, NSInternalInconsistencyException);
+ }
+
+ {
mbgl::style::NotHasFilter filter = { .key = "a" };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = nil"]);
}
-
+
{
mbgl::style::NotEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != 'b'"]);
}
{
+ mbgl::style::TypeNotEqualsFilter filter = { .value = mbgl::FeatureType::Point };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K != 'Point'", @"$type"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::IdentifierNotEqualsFilter filter = { .value = UINT64_C(67086180) };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K != 67086180", @"$id"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
+ mbgl::style::HasIdentifierFilter filter;
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K != nil", @"$id"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
mbgl::style::HasFilter filter = { .key = "a" };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != nil"]);
}
-
+
{
mbgl::style::LessThanFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a < 'b'"]);
}
-
+
{
mbgl::style::LessThanEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a <= 'b'"]);
}
-
+
{
mbgl::style::GreaterThanFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a > 'b'"]);
}
-
+
{
mbgl::style::GreaterThanEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a >= 'b'"]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -283,7 +414,7 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -293,22 +424,46 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]);
}
-
+
{
mbgl::style::InFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].predicateFormat);
}
{
+ mbgl::style::TypeInFilter filter = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K IN {'LineString', 'Polygon'}", @"$type"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, expected.predicateFormat);
+ }
+
+ {
+ mbgl::style::IdentifierInFilter filter = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
mbgl::style::NotInFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].predicateFormat);
}
{
+ mbgl::style::TypeNotInFilter filter = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"NOT %K IN {'LineString', 'Polygon'}", @"$type"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, expected.predicateFormat);
+ }
+
+ {
+ mbgl::style::IdentifierNotInFilter filter = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
+ NSPredicate *expected = [NSPredicate predicateWithFormat:@"NOT %K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
+ }
+
+ {
mbgl::style::AllFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -318,12 +473,12 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"]);
}
-
+
{
mbgl::style::AnyFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:NO]);
}
-
+
{
mbgl::style::AnyFilter filter = {
.filters = {
@@ -333,12 +488,12 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"]);
}
-
+
{
mbgl::style::NoneFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]);
}
-
+
{
mbgl::style::NoneFilter filter = {
.filters = {
@@ -355,20 +510,20 @@ namespace mbgl {
[self testSymmetryWithFormat:@"a != 1" reverseFormat:@"1 != a" mustRoundTrip:YES];
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = b"].mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 = 1"].mgl_filter, NSException, NSInvalidArgumentException);
-
+
// In the predicate format language, $ is a special character denoting a
// variable. Use %K to escape the special feature attribute $id.
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"$id == 670861802"].mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = $id"].mgl_filter, NSException, NSInvalidArgumentException);
-
+
[self testSymmetryWithFormat:@"a = nil" reverseFormat:@"nil = a" mustRoundTrip:YES];
[self testSymmetryWithFormat:@"a != nil" reverseFormat:@"nil != a" mustRoundTrip:YES];
-
+
[self testSymmetryWithFormat:@"a < 1" reverseFormat:@"1 > a" mustRoundTrip:YES];
[self testSymmetryWithFormat:@"a <= 1" reverseFormat:@"1 >= a" mustRoundTrip:YES];
[self testSymmetryWithFormat:@"a > 1" reverseFormat:@"1 < a" mustRoundTrip:YES];
[self testSymmetryWithFormat:@"a >= 1" reverseFormat:@"1 <= a" mustRoundTrip:YES];
-
+
[self testSymmetryWithFormat:@"a BETWEEN {1, 2}" reverseFormat:@"1 <= a && 2 >= a" mustRoundTrip:YES];
[self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@1, @2]]
reversePredicate:[NSPredicate predicateWithFormat:@"1 <= a && 2 >= a"]
@@ -378,12 +533,12 @@ namespace mbgl {
XCTAssertThrowsSpecificNamed(betweenSetPredicate.mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1}"].mgl_filter, NSException, NSInvalidArgumentException);
XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1, 2, 3}"].mgl_filter, NSException, NSInvalidArgumentException);
-
+
[self testSymmetryWithFormat:@"a IN {1, 2}" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO];
[self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a IN %@", @[@1, @2]]
reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
mustRoundTrip:YES];
-
+
// The reverse formats here are a bit backwards because we canonicalize
// a reverse CONTAINS to a forward IN.
[self testSymmetryWithFormat:@"{1, 2} CONTAINS a" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO];
@@ -406,12 +561,12 @@ namespace mbgl {
// example, so compare formats instead of the predicates themselves.
XCTAssertEqualObjects(forwardPredicate.predicateFormat, forwardPredicateAfter.predicateFormat);
}
-
+
if (reversePredicate) {
auto reverseFilter = reversePredicate.mgl_filter;
NSPredicate *reversePredicateAfter = [NSPredicate mgl_predicateWithFilter:reverseFilter];
XCTAssertNotEqualObjects(reversePredicate, reversePredicateAfter);
-
+
XCTAssertEqualObjects(forwardPredicateAfter, reversePredicateAfter);
}
}
diff --git a/platform/darwin/test/MGLRasterStyleLayerTests.mm b/platform/darwin/test/MGLRasterStyleLayerTests.mm
index 28a201961c..b7a764e6c2 100644
--- a/platform/darwin/test/MGLRasterStyleLayerTests.mm
+++ b/platform/darwin/test/MGLRasterStyleLayerTests.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -19,248 +19,283 @@
- (void)testProperties {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGLRasterStyleLayer *layer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::RasterLayer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::RasterLayer>();
-
+
// raster-brightness-max
{
XCTAssertTrue(rawLayer->getRasterBrightnessMax().isUndefined(),
@"raster-brightness-max should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.maximumRasterBrightness;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.maximumRasterBrightness = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.maximumRasterBrightness = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterBrightnessMax(), propertyValue,
@"Setting maximumRasterBrightness to a constant value should update raster-brightness-max.");
- XCTAssertEqualObjects(layer.maximumRasterBrightness, styleValue,
+ XCTAssertEqualObjects(layer.maximumRasterBrightness, constantStyleValue,
@"maximumRasterBrightness should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.maximumRasterBrightness = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.maximumRasterBrightness = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterBrightnessMax(), propertyValue,
- @"Setting maximumRasterBrightness to a function should update raster-brightness-max.");
- XCTAssertEqualObjects(layer.maximumRasterBrightness, styleValue,
- @"maximumRasterBrightness should round-trip functions.");
-
+ @"Setting maximumRasterBrightness to a camera function should update raster-brightness-max.");
+ XCTAssertEqualObjects(layer.maximumRasterBrightness, functionStyleValue,
+ @"maximumRasterBrightness should round-trip camera functions.");
+
+
+
layer.maximumRasterBrightness = nil;
XCTAssertTrue(rawLayer->getRasterBrightnessMax().isUndefined(),
@"Unsetting maximumRasterBrightness should return raster-brightness-max to the default value.");
XCTAssertEqualObjects(layer.maximumRasterBrightness, defaultStyleValue,
@"maximumRasterBrightness should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// raster-brightness-min
{
XCTAssertTrue(rawLayer->getRasterBrightnessMin().isUndefined(),
@"raster-brightness-min should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.minimumRasterBrightness;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.minimumRasterBrightness = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.minimumRasterBrightness = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterBrightnessMin(), propertyValue,
@"Setting minimumRasterBrightness to a constant value should update raster-brightness-min.");
- XCTAssertEqualObjects(layer.minimumRasterBrightness, styleValue,
+ XCTAssertEqualObjects(layer.minimumRasterBrightness, constantStyleValue,
@"minimumRasterBrightness should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.minimumRasterBrightness = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.minimumRasterBrightness = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterBrightnessMin(), propertyValue,
- @"Setting minimumRasterBrightness to a function should update raster-brightness-min.");
- XCTAssertEqualObjects(layer.minimumRasterBrightness, styleValue,
- @"minimumRasterBrightness should round-trip functions.");
-
+ @"Setting minimumRasterBrightness to a camera function should update raster-brightness-min.");
+ XCTAssertEqualObjects(layer.minimumRasterBrightness, functionStyleValue,
+ @"minimumRasterBrightness should round-trip camera functions.");
+
+
+
layer.minimumRasterBrightness = nil;
XCTAssertTrue(rawLayer->getRasterBrightnessMin().isUndefined(),
@"Unsetting minimumRasterBrightness should return raster-brightness-min to the default value.");
XCTAssertEqualObjects(layer.minimumRasterBrightness, defaultStyleValue,
@"minimumRasterBrightness should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// raster-contrast
{
XCTAssertTrue(rawLayer->getRasterContrast().isUndefined(),
@"raster-contrast should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterContrast;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterContrast = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.rasterContrast = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterContrast(), propertyValue,
@"Setting rasterContrast to a constant value should update raster-contrast.");
- XCTAssertEqualObjects(layer.rasterContrast, styleValue,
+ XCTAssertEqualObjects(layer.rasterContrast, constantStyleValue,
@"rasterContrast should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.rasterContrast = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.rasterContrast = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterContrast(), propertyValue,
- @"Setting rasterContrast to a function should update raster-contrast.");
- XCTAssertEqualObjects(layer.rasterContrast, styleValue,
- @"rasterContrast should round-trip functions.");
-
+ @"Setting rasterContrast to a camera function should update raster-contrast.");
+ XCTAssertEqualObjects(layer.rasterContrast, functionStyleValue,
+ @"rasterContrast should round-trip camera functions.");
+
+
+
layer.rasterContrast = nil;
XCTAssertTrue(rawLayer->getRasterContrast().isUndefined(),
@"Unsetting rasterContrast should return raster-contrast to the default value.");
XCTAssertEqualObjects(layer.rasterContrast, defaultStyleValue,
@"rasterContrast should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterContrast = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterContrast = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// raster-fade-duration
{
XCTAssertTrue(rawLayer->getRasterFadeDuration().isUndefined(),
@"raster-fade-duration should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterFadeDuration;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterFadeDuration = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.rasterFadeDuration = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterFadeDuration(), propertyValue,
@"Setting rasterFadeDuration to a constant value should update raster-fade-duration.");
- XCTAssertEqualObjects(layer.rasterFadeDuration, styleValue,
+ XCTAssertEqualObjects(layer.rasterFadeDuration, constantStyleValue,
@"rasterFadeDuration should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.rasterFadeDuration = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.rasterFadeDuration = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterFadeDuration(), propertyValue,
- @"Setting rasterFadeDuration to a function should update raster-fade-duration.");
- XCTAssertEqualObjects(layer.rasterFadeDuration, styleValue,
- @"rasterFadeDuration should round-trip functions.");
-
+ @"Setting rasterFadeDuration to a camera function should update raster-fade-duration.");
+ XCTAssertEqualObjects(layer.rasterFadeDuration, functionStyleValue,
+ @"rasterFadeDuration should round-trip camera functions.");
+
+
+
layer.rasterFadeDuration = nil;
XCTAssertTrue(rawLayer->getRasterFadeDuration().isUndefined(),
@"Unsetting rasterFadeDuration should return raster-fade-duration to the default value.");
XCTAssertEqualObjects(layer.rasterFadeDuration, defaultStyleValue,
@"rasterFadeDuration should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// raster-hue-rotate
{
XCTAssertTrue(rawLayer->getRasterHueRotate().isUndefined(),
@"raster-hue-rotate should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterHueRotation;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterHueRotation = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.rasterHueRotation = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterHueRotate(), propertyValue,
@"Setting rasterHueRotation to a constant value should update raster-hue-rotate.");
- XCTAssertEqualObjects(layer.rasterHueRotation, styleValue,
+ XCTAssertEqualObjects(layer.rasterHueRotation, constantStyleValue,
@"rasterHueRotation should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.rasterHueRotation = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.rasterHueRotation = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterHueRotate(), propertyValue,
- @"Setting rasterHueRotation to a function should update raster-hue-rotate.");
- XCTAssertEqualObjects(layer.rasterHueRotation, styleValue,
- @"rasterHueRotation should round-trip functions.");
-
+ @"Setting rasterHueRotation to a camera function should update raster-hue-rotate.");
+ XCTAssertEqualObjects(layer.rasterHueRotation, functionStyleValue,
+ @"rasterHueRotation should round-trip camera functions.");
+
+
+
layer.rasterHueRotation = nil;
XCTAssertTrue(rawLayer->getRasterHueRotate().isUndefined(),
@"Unsetting rasterHueRotation should return raster-hue-rotate to the default value.");
XCTAssertEqualObjects(layer.rasterHueRotation, defaultStyleValue,
@"rasterHueRotation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// raster-opacity
{
XCTAssertTrue(rawLayer->getRasterOpacity().isUndefined(),
@"raster-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterOpacity = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.rasterOpacity = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterOpacity(), propertyValue,
@"Setting rasterOpacity to a constant value should update raster-opacity.");
- XCTAssertEqualObjects(layer.rasterOpacity, styleValue,
+ XCTAssertEqualObjects(layer.rasterOpacity, constantStyleValue,
@"rasterOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.rasterOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.rasterOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterOpacity(), propertyValue,
- @"Setting rasterOpacity to a function should update raster-opacity.");
- XCTAssertEqualObjects(layer.rasterOpacity, styleValue,
- @"rasterOpacity should round-trip functions.");
-
+ @"Setting rasterOpacity to a camera function should update raster-opacity.");
+ XCTAssertEqualObjects(layer.rasterOpacity, functionStyleValue,
+ @"rasterOpacity should round-trip camera functions.");
+
+
+
layer.rasterOpacity = nil;
XCTAssertTrue(rawLayer->getRasterOpacity().isUndefined(),
@"Unsetting rasterOpacity should return raster-opacity to the default value.");
XCTAssertEqualObjects(layer.rasterOpacity, defaultStyleValue,
@"rasterOpacity should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// raster-saturation
{
XCTAssertTrue(rawLayer->getRasterSaturation().isUndefined(),
@"raster-saturation should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.rasterSaturation;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.rasterSaturation = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.rasterSaturation = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getRasterSaturation(), propertyValue,
@"Setting rasterSaturation to a constant value should update raster-saturation.");
- XCTAssertEqualObjects(layer.rasterSaturation, styleValue,
+ XCTAssertEqualObjects(layer.rasterSaturation, constantStyleValue,
@"rasterSaturation should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.rasterSaturation = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.rasterSaturation = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getRasterSaturation(), propertyValue,
- @"Setting rasterSaturation to a function should update raster-saturation.");
- XCTAssertEqualObjects(layer.rasterSaturation, styleValue,
- @"rasterSaturation should round-trip functions.");
-
+ @"Setting rasterSaturation to a camera function should update raster-saturation.");
+ XCTAssertEqualObjects(layer.rasterSaturation, functionStyleValue,
+ @"rasterSaturation should round-trip camera functions.");
+
+
+
layer.rasterSaturation = nil;
XCTAssertTrue(rawLayer->getRasterSaturation().isUndefined(),
@"Unsetting rasterSaturation should return raster-saturation to the default value.");
XCTAssertEqualObjects(layer.rasterSaturation, defaultStyleValue,
@"rasterSaturation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterSaturation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.rasterSaturation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}
diff --git a/platform/darwin/test/MGLShapeSourceTests.mm b/platform/darwin/test/MGLShapeSourceTests.mm
index cf32b5c821..ba85d76020 100644
--- a/platform/darwin/test/MGLShapeSourceTests.mm
+++ b/platform/darwin/test/MGLShapeSourceTests.mm
@@ -19,7 +19,7 @@
MGLShapeSourceOptionMaximumZoomLevel: @99,
MGLShapeSourceOptionBuffer: @1976,
MGLShapeSourceOptionSimplificationTolerance: @0.42};
-
+
auto mbglOptions = MGLGeoJSONOptionsFromDictionary(options);
XCTAssertTrue(mbglOptions.cluster);
XCTAssertEqual(mbglOptions.clusterRadius, 42);
@@ -27,7 +27,7 @@
XCTAssertEqual(mbglOptions.maxzoom, 99);
XCTAssertEqual(mbglOptions.buffer, 1976);
XCTAssertEqual(mbglOptions.tolerance, 0.42);
-
+
options = @{MGLShapeSourceOptionClustered: @"number 1"};
XCTAssertThrows(MGLGeoJSONOptionsFromDictionary(options));
}
@@ -41,26 +41,26 @@
NSDictionary *options = @{
MGLShapeSourceOptionClustered: @YES,
};
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"id" shape:[[MGLPointFeature alloc] init] options:options];
XCTAssertTrue([source.shape isKindOfClass:[MGLPointFeature class]]);
-
+
MGLShapeCollectionFeature *feature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[]];
source = [[MGLShapeSource alloc] initWithIdentifier:@"id" shape:feature options:options];
XCTAssertTrue([source.shape isKindOfClass:[MGLShapeCollectionFeature class]]);
}
- (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];
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];
-
+
MGLShapeCollection *collection = (MGLShapeCollection *)source.shape;
XCTAssertNotNil(collection);
XCTAssertEqual(collection.shapes.count, 1);
@@ -95,9 +95,9 @@
- (void)testMGLShapeSourceWithPolylineFeatures {
CLLocationCoordinate2D coordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates count:2];
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:polylineFeature options:nil];
-
+
XCTAssertNotNil(source.shape);
XCTAssertTrue([source.shape isMemberOfClass:[MGLPolylineFeature class]]);
}
@@ -109,7 +109,7 @@
CLLocationCoordinate2DMake(101.0, 1.0),
CLLocationCoordinate2DMake(100.0, 1.0),
CLLocationCoordinate2DMake(100.0, 0.0)};
-
+
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5];
polygonFeature.identifier = @"feature-id";
NSString *stringAttribute = @"string";
@@ -123,7 +123,7 @@
@"key-4": arrayValue};
NSArray *arrayOfArrays = @[@[@1, @"string-value", @[@"jagged"]]];
NSArray *arrayOfDictionaries = @[@{@"key": @"value"}];
-
+
polygonFeature.attributes = @{@"name": stringAttribute,
@"bool": boolAttribute,
@"double": doubleAttribute,
@@ -131,9 +131,9 @@
@"array-attribute": arrayValue,
@"array-of-array-attribute": arrayOfArrays,
@"array-of-dictionary-attribute": arrayOfDictionaries};
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:polygonFeature options:nil];
-
+
XCTAssertNotNil(source.shape);
MGLPolygonFeature *expectedPolygonFeature = (MGLPolygonFeature *)source.shape;
XCTAssertEqualObjects(expectedPolygonFeature.identifier, polygonFeature.identifier);
@@ -155,20 +155,20 @@
CLLocationCoordinate2DMake(101.0, 1.0),
CLLocationCoordinate2DMake(100.0, 1.0),
CLLocationCoordinate2DMake(100.0, 0.0)};
-
+
CLLocationCoordinate2D interiorCoordinates[] = {
CLLocationCoordinate2DMake(100.2, 0.2),
CLLocationCoordinate2DMake(100.8, 0.2),
CLLocationCoordinate2DMake(100.8, 0.8),
CLLocationCoordinate2DMake(100.2, 0.8),
CLLocationCoordinate2DMake(100.2, 0.2)};
-
+
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
-
+
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:polygonFeature options:nil];
-
+
XCTAssertNotNil(source.shape);
XCTAssertTrue([source.shape isMemberOfClass:[MGLPolygonFeature class]]);
}
@@ -179,9 +179,9 @@
CLLocationCoordinate2D secondCoordinates[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
MGLPolylineFeature *secondPolylineFeature = [MGLPolylineFeature polylineWithCoordinates:secondCoordinates count:2];
MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[firstPolylineFeature, secondPolylineFeature]];
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:multiPolylineFeature options:nil];
-
+
XCTAssertNotNil(source.shape);
XCTAssertTrue([source.shape isMemberOfClass:[MGLMultiPolylineFeature class]]);
}
@@ -193,23 +193,23 @@
CLLocationCoordinate2DMake(101.0, 1.0),
CLLocationCoordinate2DMake(100.0, 1.0),
CLLocationCoordinate2DMake(100.0, 0.0)};
-
+
CLLocationCoordinate2D interiorCoordinates[] = {
CLLocationCoordinate2DMake(100.2, 0.2),
CLLocationCoordinate2DMake(100.8, 0.2),
CLLocationCoordinate2DMake(100.8, 0.8),
CLLocationCoordinate2DMake(100.2, 0.8),
CLLocationCoordinate2DMake(100.2, 0.2)};
-
+
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
-
+
MGLPolygonFeature *firstPolygon = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
MGLPolygonFeature *secondPolygon = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
-
+
MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[firstPolygon, secondPolygon]];
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"source-id" shape:multiPolygonFeature options:nil];
-
+
XCTAssertNotNil(source.shape);
XCTAssertTrue([source.shape isMemberOfClass:[MGLMultiPolygonFeature class]]);
}
@@ -217,9 +217,9 @@
- (void)testMGLShapeSourceWithPointFeature {
MGLPointFeature *pointFeature = [MGLPointFeature new];
pointFeature.coordinate = CLLocationCoordinate2DMake(100.2, 0.2);
-
+
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"souce-id" shape:pointFeature options:nil];
-
+
XCTAssertNotNil(source.shape);
XCTAssertTrue([source.shape isMemberOfClass:[MGLPointFeature class]]);
}
@@ -245,34 +245,34 @@
CLLocationCoordinate2DMake(101.0, 1.0),
CLLocationCoordinate2DMake(100.0, 1.0),
CLLocationCoordinate2DMake(100.0, 0.0)};
-
+
CLLocationCoordinate2D interiorCoordinates[] = {
CLLocationCoordinate2DMake(100.2, 0.2),
CLLocationCoordinate2DMake(100.8, 0.2),
CLLocationCoordinate2DMake(100.8, 0.8),
CLLocationCoordinate2DMake(100.2, 0.8),
CLLocationCoordinate2DMake(100.2, 0.2)};
-
+
MGLPolygon *polygon = [MGLPolygon polygonWithCoordinates:interiorCoordinates count:5];
-
+
MGLPolygonFeature *polygonFeature = [MGLPolygonFeature polygonWithCoordinates:coordinates count:5 interiorPolygons:@[polygon]];
-
+
CLLocationCoordinate2D coordinates_2[] = { CLLocationCoordinate2DMake(0, 0), CLLocationCoordinate2DMake(10, 10)};
MGLPolylineFeature *polylineFeature = [MGLPolylineFeature polylineWithCoordinates:coordinates_2 count:2];
-
+
MGLMultiPolygonFeature *multiPolygonFeature = [MGLMultiPolygonFeature multiPolygonWithPolygons:@[polygonFeature, polygonFeature]];
-
+
MGLMultiPolylineFeature *multiPolylineFeature = [MGLMultiPolylineFeature multiPolylineWithPolylines:@[polylineFeature, polylineFeature]];
-
+
MGLPointCollectionFeature *pointCollectionFeature = [MGLPointCollectionFeature pointCollectionWithCoordinates:coordinates count:5];
-
+
MGLPointFeature *pointFeature = [MGLPointFeature new];
pointFeature.coordinate = CLLocationCoordinate2DMake(100.2, 0.2);
-
+
MGLShapeCollectionFeature *shapeCollectionFeature = [MGLShapeCollectionFeature shapeCollectionWithShapes:@[polygonFeature, polylineFeature, multiPolygonFeature, multiPolylineFeature, pointCollectionFeature, pointFeature]];
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");
diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m
index 1dba9f4305..b51fa02af4 100644
--- a/platform/darwin/test/MGLStyleLayerTests.m
+++ b/platform/darwin/test/MGLStyleLayerTests.m
@@ -11,22 +11,22 @@
- (void)testProperties {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGLFillStyleLayer *layer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
-
+
XCTAssertEqualObjects(layer.identifier, @"layerID");
XCTAssertEqualObjects(layer.sourceIdentifier, source.identifier);
-
+
XCTAssertTrue(layer.visible);
layer.visible = NO;
XCTAssertFalse(layer.visible);
layer.visible = YES;
XCTAssertTrue(layer.visible);
-
+
XCTAssertEqual(layer.minimumZoomLevel, -INFINITY);
layer.minimumZoomLevel = 22;
XCTAssertEqual(layer.minimumZoomLevel, 22);
-
+
XCTAssertEqual(layer.maximumZoomLevel, INFINITY);
layer.maximumZoomLevel = 0;
XCTAssertEqual(layer.maximumZoomLevel, 0);
diff --git a/platform/darwin/test/MGLStyleLayerTests.mm.ejs b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
index 00842a5b4e..810d7fbd3b 100644
--- a/platform/darwin/test/MGLStyleLayerTests.mm.ejs
+++ b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
@@ -3,8 +3,8 @@
const properties = locals.properties;
const enumProperties = locals.enumProperties;
-%>
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -26,13 +26,13 @@
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
MGL<%- camelize(type) %>StyleLayer *layer = [[MGL<%- camelize(type) %>StyleLayer alloc] initWithIdentifier:@"layerID" source:source];
-
+
XCTAssertNil(layer.sourceLayerIdentifier);
layer.sourceLayerIdentifier = @"layerID";
XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
layer.sourceLayerIdentifier = nil;
XCTAssertNil(layer.sourceLayerIdentifier);
-
+
XCTAssertNil(layer.predicate);
layer.predicate = [NSPredicate predicateWithValue:NO];
XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
@@ -47,48 +47,83 @@
<% } else { -%>
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGL<%- camelize(type) %>StyleLayer *layer = [[MGL<%- camelize(type) %>StyleLayer alloc] initWithIdentifier:@"layerID" source:source];
<% } -%>
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::<%- camelize(type) %>Layer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::<%- camelize(type) %>Layer>();
<% for (const property of properties) { -%>
-
+
// <%- originalPropertyName(property) %>
{
XCTAssertTrue(rawLayer->get<%- camelize(originalPropertyName(property)) %>().isUndefined(),
@"<%- originalPropertyName(property) %> should be unset initially.");
MGLStyleValue<<%- propertyType(property) %>> *defaultStyleValue = layer.<%- objCName(property) %>;
-
- MGLStyleValue<<%- propertyType(property) %>> *styleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithRawValue:<%- objCTestValue(property, type, 3) %>];
- layer.<%- objCName(property) %> = styleValue;
+
+ MGLStyleValue<<%- propertyType(property) %>> *constantStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithRawValue:<%- objCTestValue(property, type, 3) %>];
+ layer.<%- objCName(property) %> = constantStyleValue;
+<% if (property["property-function"]) { -%>
+ mbgl::style::DataDrivenPropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> };
+<% } else { -%>
mbgl::style::PropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> };
+<% } -%>
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@"Setting <%- objCName(property) %> to a constant value should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, styleValue,
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, constantStyleValue,
@"<%- objCName(property) %> should round-trip constant values.");
+
+ MGLStyleValue<<%- propertyType(property) %>> * functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.<%- objCName(property) %> = functionStyleValue;
+
+ mbgl::style::IntervalStops<<%- mbglType(property) %>> intervalStops = { {{18, <%- mbglTestValue(property, type) %>}} };
+ propertyValue = mbgl::style::CameraFunction<<%- mbglType(property) %>> { intervalStops };
- styleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithStops:@{
- @18: styleValue,
- }];
- layer.<%- objCName(property) %> = styleValue;
- propertyValue = { mbgl::style::Function<<%- mbglType(property) %>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
- @"Setting <%- objCName(property) %> to a function should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, styleValue,
- @"<%- objCName(property) %> should round-trip functions.");
+ @"Setting <%- objCName(property) %> to a camera function should update <%- originalPropertyName(property) %>.");
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionStyleValue,
+ @"<%- objCName(property) %> should round-trip camera functions.");
+
+<% if (property["property-function"] && isInterpolatable(property)) { -%>
+ functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.<%- objCName(property) %> = functionStyleValue;
+
+ mbgl::style::ExponentialStops<<%- mbglType(property) %>> exponentialStops = { {{18, <%- mbglTestValue(property, type) %>}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<<%- mbglType(property) %>> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
+ @"Setting <%- objCName(property) %> to a source function should update <%- originalPropertyName(property) %>.");
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionStyleValue,
+ @"<%- objCName(property) %> should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.<%- objCName(property) %> = functionStyleValue;
+
+ std::map<float, <%- mbglType(property) %>> innerStops { {18, <%- mbglTestValue(property, type) %>} };
+ mbgl::style::CompositeExponentialStops<<%- mbglType(property) %>> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<<%- mbglType(property) %>> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
+ @"Setting <%- objCName(property) %> to a composite function should update <%- originalPropertyName(property) %>.");
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionStyleValue,
+ @"<%- objCName(property) %> should round-trip composite functions.");
+<% } -%>
<% if (!property.required) { -%>
-
+
layer.<%- objCName(property) %> = nil;
XCTAssertTrue(rawLayer->get<%- camelize(originalPropertyName(property)) %>().isUndefined(),
@"Unsetting <%- objCName(property) %> should return <%- originalPropertyName(property) %> to the default value.");
XCTAssertEqualObjects(layer.<%- objCName(property) %>, defaultStyleValue,
@"<%- objCName(property) %> should return the default value after being unset.");
<% } -%>
+<% if (!property["property-function"]) { -%>
+
+ functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<<%- propertyType(property) %>> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+<% } -%>
}
<% } -%>
}
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index 176217619d..c50330d488 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -25,7 +25,7 @@
- (void)setUp {
[super setUp];
-
+
[MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
self.mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) styleURL:styleURL];
@@ -39,14 +39,14 @@
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
XCTAssertNotNil(mapView.style);
XCTAssertEqual(mapView.style, style);
-
+
[_styleLoadingExpectation fulfill];
}
- (void)tearDown {
_styleLoadingExpectation = nil;
self.mapView = nil;
-
+
[super tearDown];
}
@@ -81,7 +81,7 @@
XCTAssertEqualObjects([MGLStyle satelliteStyleURLWithVersion:99].absoluteString, @"mapbox://styles/mapbox/satellite-v99");
XCTAssertEqualObjects([MGLStyle satelliteStreetsStyleURLWithVersion:MGLStyleDefaultVersion].absoluteString, @(mbgl::util::default_styles::satelliteStreets.url));
XCTAssertEqualObjects([MGLStyle satelliteStreetsStyleURLWithVersion:99].absoluteString, @"mapbox://styles/mapbox/satellite-streets-v99");
-
+
static_assert(6 == mbgl::util::default_styles::numOrderedStyles,
"MGLStyleTests isn’t testing all the styles in mbgl::util::default_styles.");
}
@@ -109,17 +109,17 @@
XCTAssertEqual(mbgl::util::default_styles::numOrderedStyles, numVersionedMethods,
@"There are %lu default styles but MGLStyleTests only provides versioned style URL methods for %u of them.",
mbgl::util::default_styles::numOrderedStyles, numVersionedMethods);
-
+
// Test that all the versioned style methods are in the public header.
NSString *styleHeader = self.stringWithContentsOfStyleHeader;
-
+
NSError *versionedMethodError;
NSString *versionedMethodExpressionString = @(R"RE(^\+\s*\(NSURL\s*\*\s*\)\s*\w+StyleURLWithVersion\s*:\s*\(\s*NSInteger\s*\)\s*version\s*;)RE");
NSRegularExpression *versionedMethodExpression = [NSRegularExpression regularExpressionWithPattern:versionedMethodExpressionString options:NSRegularExpressionAnchorsMatchLines error:&versionedMethodError];
XCTAssertNil(versionedMethodError, @"Error compiling regular expression to search for versioned methods.");
NSUInteger numVersionedMethodDeclarations = [versionedMethodExpression numberOfMatchesInString:styleHeader options:0 range:NSMakeRange(0, styleHeader.length)];
XCTAssertEqual(numVersionedMethodDeclarations, numVersionedMethods);
-
+
// Test that “current version is” statements are present and current for all versioned style methods.
NSError *versionError;
NSString *versionExpressionString = @(R"RE(current version is `(\d+)`)RE");
@@ -219,15 +219,15 @@
}
- (void)testAddingLayersWithDuplicateIdentifiers {
- //Just some source
+ // Just some source
MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
[self.style addSource: source];
-
- //Add initial layer
+
+ // Add initial layer
MGLFillStyleLayer *initial = [[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source];
[self.style addLayer:initial];
-
- //Try to add the duplicate
+
+ // Try to add the duplicate
XCTAssertThrowsSpecificNamed([self.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException");
XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException");
XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException");
@@ -246,7 +246,10 @@
}
- (void)testClasses {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
XCTAssertEqual(self.style.styleClasses.count, 0);
+#pragma clang diagnostic pop
}
- (void)testImages {
@@ -259,10 +262,10 @@
MGLImage *image = [[NSBundle bundleForClass:[self class]] imageForResource:imageName];
#endif
XCTAssertNotNil(image);
-
+
[self.style setImage:image forName:imageName];
MGLImage *styleImage = [self.style imageForName:imageName];
-
+
XCTAssertNotNil(styleImage);
XCTAssertEqual(image.size.width, styleImage.size.width);
XCTAssertEqual(image.size.height, styleImage.size.height);
@@ -273,28 +276,28 @@
NSURL *url = [NSURL fileURLWithPath:filePath];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil];
[self.style addSource:source];
-
+
MGLCircleStyleLayer *layer1 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer1" source:source];
[self.style addLayer:layer1];
-
+
MGLCircleStyleLayer *layer3 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer3" source:source];
[self.style addLayer:layer3];
-
+
MGLCircleStyleLayer *layer2 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer2" source:source];
[self.style insertLayer:layer2 aboveLayer:layer1];
-
+
MGLCircleStyleLayer *layer4 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer4" source:source];
[self.style insertLayer:layer4 aboveLayer:layer3];
-
+
MGLCircleStyleLayer *layer0 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer0" source:source];
[self.style insertLayer:layer0 belowLayer:layer1];
-
+
NSArray<MGLStyleLayer *> *layers = [self.style layers];
NSUInteger startIndex = 0;
if ([layers.firstObject.identifier isEqualToString:@"com.mapbox.annotations.points"]) {
startIndex++;
}
-
+
XCTAssertEqualObjects(layers[startIndex++].identifier, layer0.identifier);
XCTAssertEqualObjects(layers[startIndex++].identifier, layer1.identifier);
XCTAssertEqualObjects(layers[startIndex++].identifier, layer2.identifier);
diff --git a/platform/darwin/test/MGLStyleValueTests.m b/platform/darwin/test/MGLStyleValueTests.m
index fe6096584d..cd6eec8324 100644
--- a/platform/darwin/test/MGLStyleValueTests.m
+++ b/platform/darwin/test/MGLStyleValueTests.m
@@ -7,7 +7,107 @@
@implementation MGLStyleValueTests
- (void)testStoplessFunction {
- XCTAssertThrowsSpecificNamed([MGLStyleValue<NSNumber *> valueWithStops:@{}], NSException, NSInvalidArgumentException, @"Stopless function should raise an exception");
+ XCTAssertThrowsSpecificNamed([MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential cameraStops:@{} options:nil], NSException, NSInvalidArgumentException, @"Stopless function should raise an exception");
+}
+
+- (void)testDeprecatedFunctions {
+ MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"test"
+ shape:nil
+ options:nil];
+ MGLSymbolStyleLayer *symbolStyleLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"symbolLayer"
+ source:shapeSource];
+ MGLCircleStyleLayer *circleStyleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"circleLayer"
+ source:shapeSource];
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ // deprecated function, stops with float values
+ NSDictionary<NSNumber *, MGLStyleValue<NSNumber *> *> *stops = @{
+ @1: [MGLStyleValue<NSNumber *> valueWithRawValue:@0],
+ @2: [MGLStyleValue<NSNumber *> valueWithRawValue:@1],
+ @3: [MGLStyleValue<NSNumber *> valueWithRawValue:@2],
+ @4: [MGLStyleValue<NSNumber *> valueWithRawValue:@0],
+ };
+ MGLStyleValue<NSNumber *> *iconHaloBlurStyleValue =
+ [MGLStyleValue<NSNumber *> valueWithInterpolationBase:1.0 stops:stops];
+ symbolStyleLayer.iconHaloBlur = iconHaloBlurStyleValue;
+ XCTAssertEqualObjects(symbolStyleLayer.iconHaloBlur, iconHaloBlurStyleValue);
+
+ // deprecated function, stops with boolean values
+ stops = @{
+ @1: [MGLStyleValue<NSNumber *> valueWithRawValue:@YES],
+ @2: [MGLStyleValue<NSNumber *> valueWithRawValue:@NO],
+ @3: [MGLStyleValue<NSNumber *> valueWithRawValue:@YES],
+ @4: [MGLStyleValue<NSNumber *> valueWithRawValue:@NO],
+ };
+ MGLStyleValue<NSNumber *> *iconAllowsOverlapStyleValue =
+ [MGLStyleValue<NSNumber *> valueWithInterpolationBase:1.0 stops:stops];
+ symbolStyleLayer.iconAllowsOverlap = iconAllowsOverlapStyleValue;
+ // iconAllowsOverlap is boolean so mgl and mbgl conversions will coerce the developers stops into interval stops
+ MGLStyleValue<NSNumber *> *expectedIconAllowsOverlapStyleValue =
+ [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval
+ cameraStops:stops
+ options:nil];
+ XCTAssertEqualObjects(symbolStyleLayer.iconAllowsOverlap, expectedIconAllowsOverlapStyleValue);
+
+ ///
+ // creating and using MGLStyleFunctions directly
+ ///
+
+ NSDictionary<NSNumber *, MGLStyleValue<NSNumber *> *> *circleRadiusStops = @{
+ @0: [MGLStyleValue<NSNumber *> valueWithRawValue:@10],
+ @20: [MGLStyleValue<NSNumber *> valueWithRawValue:@5],
+ };
+ MGLStyleFunction<NSNumber *> *circleRadiusFunction =
+ [MGLStyleFunction<NSNumber *> functionWithInterpolationBase:1.0
+ stops:circleRadiusStops];
+ circleStyleLayer.circleRadius = circleRadiusFunction;
+ MGLStyleValue<NSNumber *> *expectedCircleRadiusFunction =
+ [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:circleRadiusStops
+ options:nil];
+ // setting a data driven property to an MGLStyleFunction should return an exponential camera function
+ XCTAssertEqualObjects(circleStyleLayer.circleRadius, expectedCircleRadiusFunction);
+
+ CGVector circleTranslationOne = CGVectorMake(100, 0);
+ CGVector circleTranslationTwo = CGVectorMake(0, 0);
+#if TARGET_OS_IPHONE
+ NSValue *circleTranslationValueOne = [NSValue valueWithCGVector:circleTranslationOne];
+ NSValue *circleTranslationValueTwo = [NSValue valueWithCGVector:circleTranslationTwo];
+#else
+ NSValue *circleTranslationValueOne = [NSValue value:&circleTranslationOne withObjCType:@encode(CGVector)];
+ NSValue *circleTranslationValueTwo = [NSValue value:&circleTranslationTwo withObjCType:@encode(CGVector)];
+#endif
+
+ NSDictionary<NSNumber *, MGLStyleValue<NSValue *> *> *circleTranslationStops = @{
+ @0: [MGLStyleValue<NSValue *> valueWithRawValue:circleTranslationValueOne],
+ @10: [MGLStyleValue<NSValue *> valueWithRawValue:circleTranslationValueTwo],
+ };
+ MGLStyleFunction<NSValue *> *circleTranslationFunction =
+ [MGLStyleFunction<NSValue *> functionWithInterpolationBase:1.0
+ stops:circleTranslationStops];
+ circleStyleLayer.circleTranslation = circleTranslationFunction;
+ MGLStyleValue<NSValue *> *expectedCircleTranslationFunction =
+ [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential
+ cameraStops:circleTranslationStops
+ options:nil];
+ // setting a non-data driven, interpolatable property to an MGLStyleFunction should return an exponential camera function
+ XCTAssertEqualObjects(circleStyleLayer.circleTranslation, expectedCircleTranslationFunction);
+
+ NSDictionary<NSNumber *, MGLStyleValue<NSNumber *> *> *iconOptionalStops = @{
+ @0: [MGLStyleValue<NSNumber *> valueWithRawValue:@NO],
+ @20: [MGLStyleValue<NSNumber *> valueWithRawValue:@YES],
+ };
+ MGLStyleFunction<NSNumber *> *iconOptionalFunction =
+ [MGLStyleFunction<NSNumber *> valueWithInterpolationBase:1.0
+ stops:iconOptionalStops];
+ symbolStyleLayer.iconOptional = iconOptionalFunction;
+ MGLStyleValue<NSNumber *> *expectedIconOptionalFunction =
+ [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval
+ cameraStops:iconOptionalStops
+ options:nil];
+ XCTAssertEqualObjects(symbolStyleLayer.iconOptional, expectedIconOptionalFunction);
+#pragma clang diagnostic pop
}
@end
diff --git a/platform/darwin/test/MGLStyleValueTests.swift b/platform/darwin/test/MGLStyleValueTests.swift
index 18b6a901de..f965c31e40 100644
--- a/platform/darwin/test/MGLStyleValueTests.swift
+++ b/platform/darwin/test/MGLStyleValueTests.swift
@@ -1,12 +1,93 @@
import XCTest
import Mapbox
-
+#if os(iOS) || os(watchOS) || os(tvOS)
+typealias MGLColor = UIColor
+#elseif os(macOS)
+typealias MGLColor = NSColor
+#endif
+
extension MGLStyleValueTests {
+ func assertColorsEqualWithAccuracy(_ actual: MGLColor, _ expected: MGLColor, accuracy: Float = 1/255) {
+ var actualComponents : [CGFloat] = [0, 0, 0, 0]
+ var expectedComponents : [CGFloat] = [0, 0, 0, 0]
+ actual.getRed(&(actualComponents[0]), green: &(actualComponents[1]), blue: &(actualComponents[2]), alpha: &(actualComponents[3]))
+ expected.getRed(&(expectedComponents[0]), green: &(expectedComponents[1]), blue: &(expectedComponents[2]), alpha: &(expectedComponents[3]))
+ for (ac, ec) in zip(actualComponents, expectedComponents) {
+ XCTAssertEqualWithAccuracy(Float(ac), Float(ec), accuracy: accuracy)
+ }
+ }
+
+ func assertColorValuesEqual(_ actual: MGLStyleValue<MGLColor>, _ expected: MGLStyleValue<MGLColor>) {
+ guard type(of: actual) == type(of: expected) else {
+ XCTFail("Expected \(type(of: expected)), but found \(type(of: actual)) instead.")
+ return
+ }
+
+ if let actualConstant = actual as? MGLStyleConstantValue<MGLColor> {
+ assertColorsEqualWithAccuracy(actualConstant.rawValue, (expected as! MGLStyleConstantValue<MGLColor>).rawValue)
+ } else if let actualFunction = actual as? MGLStyleFunction<MGLColor>,
+ let expectedFunction = expected as? MGLStyleFunction<MGLColor> {
+
+ // unless we have stops, there's no need for a custom comparison - default to plain == assertion
+ guard let actualStops = actualFunction.stops, let expectedStops = expectedFunction.stops else {
+ XCTAssertEqual(actualFunction, expectedFunction)
+ return
+ }
+
+ guard expectedStops is [String: Any] || expectedStops is [Float:Any] else {
+ XCTFail("Stop levels must be String or Float.")
+ return
+ }
+
+ XCTAssertEqual(actualFunction.interpolationBase, expectedFunction.interpolationBase)
+ XCTAssertEqual(actualFunction.interpolationMode, expectedFunction.interpolationMode)
+ if let actualFunction = actualFunction as? MGLSourceStyleFunction<MGLColor>,
+ let expectedFunction = expectedFunction as? MGLSourceStyleFunction<MGLColor> {
+ XCTAssertEqual(actualFunction.defaultValue, expectedFunction.defaultValue)
+ } else if let actualFunction = actualFunction as? MGLCompositeStyleFunction<MGLColor>,
+ let expectedFunction = expectedFunction as? MGLCompositeStyleFunction<MGLColor> {
+ XCTAssertEqual(actualFunction.defaultValue, expectedFunction.defaultValue)
+ }
+
+ func assertStopEqual (_ actualValue: Any?, _ expectedValue: Any?) {
+ guard type(of: actualValue) == type(of: expectedValue) else {
+ XCTFail("Expected stop value of type \(type(of: expectedValue)), but found \(type(of: actualValue)) instead.")
+ return
+ }
+ if let actualValue = actualValue as? MGLStyleConstantValue<MGLColor>,
+ let expectedValue = expectedValue as? MGLStyleConstantValue<MGLColor> {
+ assertColorsEqualWithAccuracy(actualValue.rawValue, expectedValue.rawValue)
+ } else if let actualValue = actualValue as? MGLStyleConstantValue<AnyObject>,
+ let expectedValue = expectedValue as? MGLStyleConstantValue<AnyObject> {
+ XCTAssertEqual(actualValue, expectedValue)
+ } else {
+ XCTFail("Unsupported stop value type \(type(of: actualValue)).")
+ }
+ }
+
+ XCTAssertEqual(actualStops.count, expectedStops.count)
+ if let actualStops = actualStops as? [String:Any], let expectedStops = expectedStops as? [String: Any] {
+ for (key, value) in actualStops {
+ assertStopEqual(value, expectedStops[key])
+ }
+ } else if let actualStops = actualStops as? [Float:Any], let expectedStops = expectedStops as? [Float:Any] {
+ for (key, value) in actualStops {
+ assertStopEqual(value, expectedStops[key])
+ }
+ } else {
+ XCTFail("Expected stops of type \(type(of: Array(expectedStops.keys)).Index.self), but found \(type(of: Array(actualStops.keys)).Index.self) instead.")
+ return
+ }
+ } else {
+ XCTFail("MGLStyleValue<MGLColor> must be either a constant or a style function.")
+ }
+ }
func testConstantValues() {
- let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil)
- let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: shapeSource)
+ let shapeSource = MGLShapeSource(identifier: "source", shape: nil, options: nil)
+ let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "symbolLayer", source: shapeSource)
+ let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
// Boolean
symbolStyleLayer.iconAllowsOverlap = MGLStyleConstantValue(rawValue: true)
@@ -19,20 +100,198 @@ extension MGLStyleValueTests {
// String
symbolStyleLayer.text = MGLStyleConstantValue(rawValue: "{name}")
XCTAssertEqual((symbolStyleLayer.text as! MGLStyleConstantValue<NSString>).rawValue, "{name}")
+
+ var circleTranslationOne = CGVector(dx: 100, dy: 0)
+ let circleTranslationValueOne = NSValue(bytes: &circleTranslationOne, objCType: "{CGVector=dd}")
+
+ // non-data-driven (interpolatable property value), set to constant style value
+ let expectedCircleTranslationValue = MGLStyleValue<NSValue>(rawValue: circleTranslationValueOne)
+ circleStyleLayer.circleTranslation = expectedCircleTranslationValue
+ XCTAssertEqual(circleStyleLayer.circleTranslation, expectedCircleTranslationValue)
+
+ // non-data-driven (enumeration property value), set to constant style value
+ let expectedCircleScaleAlignmentValue = MGLStyleValue<NSValue>(rawValue: NSValue(mglCircleScaleAlignment: .map))
+ circleStyleLayer.circleScaleAlignment = expectedCircleScaleAlignmentValue
+ XCTAssertEqual(circleStyleLayer.circleScaleAlignment, expectedCircleScaleAlignmentValue)
}
-
- func testFunctions() {
+
+ func testFunctionsWithNonDataDrivenProperties() {
+ let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil)
+ let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
+
+ var circleTranslationOne = CGVector(dx: 100, dy: 0)
+ let circleTranslationValueOne = NSValue(bytes: &circleTranslationOne, objCType: "{CGVector=dd}")
+ var circleTranslationTwo = CGVector(dx: 0, dy: 0)
+ let circleTranslationValueTwo = NSValue(bytes: &circleTranslationTwo, objCType: "{CGVector=dd}")
+
+ let circleTranslationStops : [Float:MGLStyleValue<NSValue>] = [
+ 0: MGLStyleValue<NSValue>(rawValue: circleTranslationValueOne),
+ 10: MGLStyleValue<NSValue>(rawValue: circleTranslationValueTwo)
+ ]
+
+ // non-data-driven (interpolatable property value), camera function with CGVector (NSValue) stop values
+ let expectedCircleTranslationValue = MGLStyleValue<NSValue>(
+ interpolationMode: .interval,
+ cameraStops: circleTranslationStops,
+ options: nil
+ )
+ circleStyleLayer.circleTranslation = expectedCircleTranslationValue
+ XCTAssertEqual(circleStyleLayer.circleTranslation, expectedCircleTranslationValue)
+
+ // non-data-driven (enumeration property value), camera function with MGLCircleScaleAlignment enum (NSValue) stop values
+ let scaleAlignmentStops : [Float:MGLStyleValue<NSValue>] = [
+ 0: MGLStyleValue(rawValue: NSValue(mglCircleScaleAlignment: .map)),
+ 10: MGLStyleValue(rawValue: NSValue(mglCircleScaleAlignment: .viewport))
+ ]
+ let expectedCircleScaleAlignmentValue = MGLStyleValue<NSValue>(
+ interpolationMode: .interval,
+ cameraStops: scaleAlignmentStops,
+ options: nil
+ )
+ circleStyleLayer.circleScaleAlignment = expectedCircleScaleAlignmentValue
+ XCTAssertEqual(circleStyleLayer.circleScaleAlignment, expectedCircleScaleAlignmentValue)
+ }
+
+ func testFunctionsWithDataDrivenProperties() {
let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil)
- let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "test", source: shapeSource)
+ let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
- // Boolean
- let stops: [NSNumber: MGLStyleValue<NSNumber>] = [
- 1: MGLStyleValue(rawValue: true),
- 2: MGLStyleValue(rawValue: false),
- 3: MGLStyleValue(rawValue: true),
- 4: MGLStyleValue(rawValue: false),
- ]
- symbolStyleLayer.iconAllowsOverlap = MGLStyleFunction<NSNumber>(interpolationBase: 1, stops: stops)
- XCTAssertEqual((symbolStyleLayer.iconAllowsOverlap as! MGLStyleFunction<NSNumber>), MGLStyleFunction(interpolationBase: 1, stops: stops))
+ // data-driven, camera function with exponential color stop values
+ let redGreenStops : [Float:MGLStyleValue<MGLColor>] = [
+ 0: MGLStyleValue<MGLColor>(rawValue: .red),
+ 10: MGLStyleValue<MGLColor>(rawValue: .red),
+ 15: MGLStyleValue<MGLColor>(rawValue: .green)
+ ]
+ let expectedCircleColorValue = MGLStyleValue<MGLColor>(
+ interpolationMode: .exponential,
+ cameraStops: redGreenStops,
+ options: [.interpolationBase: 10.0]
+ )
+ circleStyleLayer.circleColor = expectedCircleColorValue
+ assertColorValuesEqual(circleStyleLayer.circleColor as! MGLStyleFunction<MGLColor>, expectedCircleColorValue as! MGLStyleFunction<MGLColor>)
+
+ // data-driven, source function with categorical color stop values with string attribute keys
+ let redOnlyStops = [
+ "red": MGLStyleValue<MGLColor>(rawValue: .red)
+ ]
+ let expectedRedCategoricalValue = MGLStyleValue<MGLColor>(
+ interpolationMode: .categorical,
+ sourceStops: redOnlyStops,
+ attributeName: "red",
+ options: [.defaultValue: MGLStyleValue<MGLColor>(rawValue: .cyan)]
+ )
+ circleStyleLayer.circleColor = expectedRedCategoricalValue
+ assertColorValuesEqual(circleStyleLayer.circleColor, expectedRedCategoricalValue)
+
+ // data-driven, source function with categorical color stop values with integer attribute keys
+ let greenOrangeStops : [Float:MGLStyleValue<MGLColor>] = [
+ 0: MGLStyleValue<MGLColor>(rawValue: .green),
+ 100: MGLStyleValue<MGLColor>(rawValue: .orange)
+ ]
+ let expectedGreenOrangeCategoricalValue = MGLStyleValue<MGLColor>(
+ interpolationMode: .categorical,
+ sourceStops: greenOrangeStops,
+ attributeName: "temp",
+ options: [.defaultValue: MGLStyleValue<MGLColor>(rawValue: .red)]
+ )
+ circleStyleLayer.circleColor = expectedGreenOrangeCategoricalValue
+ assertColorValuesEqual(circleStyleLayer.circleColor, expectedGreenOrangeCategoricalValue)
+
+ // data-driven, source function with exponential color stop values
+ let expectedRedGreenSourceExponentialValue = MGLStyleValue<MGLColor>(
+ interpolationMode: .exponential,
+ sourceStops: redGreenStops,
+ attributeName: "temp",
+ options: nil
+ )
+ circleStyleLayer.circleColor = expectedRedGreenSourceExponentialValue
+ assertColorValuesEqual(circleStyleLayer.circleColor, expectedRedGreenSourceExponentialValue)
+
+ // data-driven, identity source function
+ let expectedSourceIdentityValue = MGLStyleValue<MGLColor>(
+ interpolationMode: .identity,
+ sourceStops: nil,
+ attributeName: "size",
+ options: [.defaultValue: MGLStyleValue<MGLColor>(rawValue: .green)]
+ )
+ circleStyleLayer.circleColor = expectedSourceIdentityValue
+ assertColorValuesEqual(circleStyleLayer.circleColor, expectedSourceIdentityValue)
+
+ // data-driven, source function with categorical color stop values with boolean attribute keys
+ let booleanCategoricalStops = [
+ false: MGLStyleValue<NSNumber>(rawValue: 0),
+ true: MGLStyleValue<NSNumber>(rawValue: 2)
+ ]
+ let expectedCircleBlurCategoricalValue = MGLStyleValue<NSNumber>(
+ interpolationMode: .categorical,
+ sourceStops: booleanCategoricalStops,
+ attributeName: "fuzzy",
+ options: [.defaultValue: MGLStyleValue<NSNumber>(rawValue: 42)]
+ )
+ circleStyleLayer.circleBlur = expectedCircleBlurCategoricalValue
+ XCTAssertEqual(circleStyleLayer.circleBlur, expectedCircleBlurCategoricalValue)
+
+ // data-driven, composite function with inner categorical color stop values with string attribute keys nested in outer camera stops
+ let smallRadius = MGLStyleValue<NSNumber>(rawValue: 5)
+ let mediumRadius = MGLStyleValue<NSNumber>(rawValue: 10)
+ let largeRadius = MGLStyleValue<NSNumber>(rawValue: 20)
+ let radiusCompositeCategoricalStops: [Float: [String: MGLStyleValue<NSNumber>]] = [
+ 0: ["green": smallRadius],
+ 10: ["green": smallRadius],
+ 15: ["green": largeRadius],
+ 20: ["green": largeRadius]
+ ]
+ let defaultRadius = MGLStyleValue<NSNumber>(rawValue: 2)
+ let expectedCompositeCategoricalValue = MGLStyleValue<NSNumber>(
+ interpolationMode: .categorical,
+ compositeStops: radiusCompositeCategoricalStops,
+ attributeName: "color",
+ options: [.defaultValue: defaultRadius]
+ )
+ circleStyleLayer.circleRadius = expectedCompositeCategoricalValue
+ XCTAssertEqual(circleStyleLayer.circleRadius, expectedCompositeCategoricalValue)
+
+ // data-driven, composite function with inner exponential color stop values nested in outer camera stops
+ let radiusCompositeExponentialOrIntervalStops: [Float: [Float: MGLStyleValue<NSNumber>]] = [
+ 0: [0: smallRadius],
+ 10: [200: smallRadius],
+ 20: [200: largeRadius]
+ ]
+ let expectedCompositeExponentialValue = MGLStyleValue<NSNumber>(
+ interpolationMode: .exponential,
+ compositeStops: radiusCompositeExponentialOrIntervalStops,
+ attributeName: "temp",
+ options: [.defaultValue: mediumRadius]
+ )
+ circleStyleLayer.circleRadius = expectedCompositeExponentialValue
+ XCTAssertEqual(circleStyleLayer.circleRadius, expectedCompositeExponentialValue)
+
+ // get a value back
+ if let returnedCircleRadius = circleStyleLayer.circleRadius as? MGLCompositeStyleFunction<NSNumber> {
+ if let returnedStops = returnedCircleRadius.stops as NSDictionary? as? [NSNumber: [NSNumber: MGLStyleValue<NSNumber>]] {
+ let lhs: MGLStyleValue<NSNumber> = returnedStops[0]!.values.first!
+ let rhs: MGLStyleValue<NSNumber> = radiusCompositeExponentialOrIntervalStops[0]!.values.first!
+ XCTAssertEqual(lhs, rhs)
+ }
+ }
+
+ // get value back as base class
+ if let returnedCircleRadius = circleStyleLayer.circleRadius as? MGLStyleFunction<NSNumber> {
+ if let returnedStops = returnedCircleRadius.stops as NSDictionary? as? [NSNumber: [NSNumber: MGLStyleValue<NSNumber>]] {
+ let lhs: MGLStyleValue<NSNumber> = returnedStops[0]!.values.first!
+ let rhs: MGLStyleValue<NSNumber> = radiusCompositeExponentialOrIntervalStops[0]!.values.first!
+ XCTAssertEqual(lhs, rhs)
+ }
+ }
+
+ // data-driven, composite function with inner interval color stop values nested in outer camera stops
+ let expectedCompositeIntervalValue = MGLStyleValue<NSNumber>(
+ interpolationMode: .interval,
+ compositeStops: radiusCompositeExponentialOrIntervalStops,
+ attributeName: "temp",
+ options: nil
+ )
+ circleStyleLayer.circleRadius = expectedCompositeIntervalValue
+ XCTAssertEqual(circleStyleLayer.circleRadius, expectedCompositeIntervalValue)
}
}
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index c4dee559fc..ce4aa11cee 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -1,5 +1,5 @@
-// This file is generated.
-// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
#import "MGLStyleLayerTests.h"
@@ -20,13 +20,13 @@
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
MGLSymbolStyleLayer *layer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
-
+
XCTAssertNil(layer.sourceLayerIdentifier);
layer.sourceLayerIdentifier = @"layerID";
XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
layer.sourceLayerIdentifier = nil;
XCTAssertNil(layer.sourceLayerIdentifier);
-
+
XCTAssertNil(layer.predicate);
layer.predicate = [NSPredicate predicateWithValue:NO];
XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
@@ -37,1672 +37,1938 @@
- (void)testProperties {
MGLPointFeature *feature = [[MGLPointFeature alloc] init];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
-
+
MGLSymbolStyleLayer *layer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
XCTAssertNotEqual(layer.rawLayer, nullptr);
XCTAssertTrue(layer.rawLayer->is<mbgl::style::SymbolLayer>());
auto rawLayer = layer.rawLayer->as<mbgl::style::SymbolLayer>();
-
+
// icon-allow-overlap
{
XCTAssertTrue(rawLayer->getIconAllowOverlap().isUndefined(),
@"icon-allow-overlap should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconAllowsOverlap;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.iconAllowsOverlap = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.iconAllowsOverlap = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconAllowOverlap(), propertyValue,
@"Setting iconAllowsOverlap to a constant value should update icon-allow-overlap.");
- XCTAssertEqualObjects(layer.iconAllowsOverlap, styleValue,
+ XCTAssertEqualObjects(layer.iconAllowsOverlap, constantStyleValue,
@"iconAllowsOverlap should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconAllowsOverlap = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconAllowsOverlap = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconAllowOverlap(), propertyValue,
- @"Setting iconAllowsOverlap to a function should update icon-allow-overlap.");
- XCTAssertEqualObjects(layer.iconAllowsOverlap, styleValue,
- @"iconAllowsOverlap should round-trip functions.");
-
+ @"Setting iconAllowsOverlap to a camera function should update icon-allow-overlap.");
+ XCTAssertEqualObjects(layer.iconAllowsOverlap, functionStyleValue,
+ @"iconAllowsOverlap should round-trip camera functions.");
+
+
+
layer.iconAllowsOverlap = nil;
XCTAssertTrue(rawLayer->getIconAllowOverlap().isUndefined(),
@"Unsetting iconAllowsOverlap should return icon-allow-overlap to the default value.");
XCTAssertEqualObjects(layer.iconAllowsOverlap, defaultStyleValue,
@"iconAllowsOverlap should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-ignore-placement
{
XCTAssertTrue(rawLayer->getIconIgnorePlacement().isUndefined(),
@"icon-ignore-placement should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconIgnoresPlacement;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.iconIgnoresPlacement = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.iconIgnoresPlacement = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconIgnorePlacement(), propertyValue,
@"Setting iconIgnoresPlacement to a constant value should update icon-ignore-placement.");
- XCTAssertEqualObjects(layer.iconIgnoresPlacement, styleValue,
+ XCTAssertEqualObjects(layer.iconIgnoresPlacement, constantStyleValue,
@"iconIgnoresPlacement should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconIgnoresPlacement = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconIgnoresPlacement = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconIgnorePlacement(), propertyValue,
- @"Setting iconIgnoresPlacement to a function should update icon-ignore-placement.");
- XCTAssertEqualObjects(layer.iconIgnoresPlacement, styleValue,
- @"iconIgnoresPlacement should round-trip functions.");
-
+ @"Setting iconIgnoresPlacement to a camera function should update icon-ignore-placement.");
+ XCTAssertEqualObjects(layer.iconIgnoresPlacement, functionStyleValue,
+ @"iconIgnoresPlacement should round-trip camera functions.");
+
+
+
layer.iconIgnoresPlacement = nil;
XCTAssertTrue(rawLayer->getIconIgnorePlacement().isUndefined(),
@"Unsetting iconIgnoresPlacement should return icon-ignore-placement to the default value.");
XCTAssertEqualObjects(layer.iconIgnoresPlacement, defaultStyleValue,
@"iconIgnoresPlacement should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-image
{
XCTAssertTrue(rawLayer->getIconImage().isUndefined(),
@"icon-image should be unset initially.");
MGLStyleValue<NSString *> *defaultStyleValue = layer.iconImageName;
-
- MGLStyleValue<NSString *> *styleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Icon Image"];
- layer.iconImageName = styleValue;
+
+ MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Icon Image"];
+ layer.iconImageName = constantStyleValue;
mbgl::style::PropertyValue<std::string> propertyValue = { "Icon Image" };
XCTAssertEqual(rawLayer->getIconImage(), propertyValue,
@"Setting iconImageName to a constant value should update icon-image.");
- XCTAssertEqualObjects(layer.iconImageName, styleValue,
+ XCTAssertEqualObjects(layer.iconImageName, constantStyleValue,
@"iconImageName should round-trip constant values.");
+
+ MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconImageName = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Icon Image"}} };
+ propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
- styleValue = [MGLStyleValue<NSString *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconImageName = styleValue;
- propertyValue = { mbgl::style::Function<std::string> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconImage(), propertyValue,
- @"Setting iconImageName to a function should update icon-image.");
- XCTAssertEqualObjects(layer.iconImageName, styleValue,
- @"iconImageName should round-trip functions.");
-
+ @"Setting iconImageName to a camera function should update icon-image.");
+ XCTAssertEqualObjects(layer.iconImageName, functionStyleValue,
+ @"iconImageName should round-trip camera functions.");
+
+
+
layer.iconImageName = nil;
XCTAssertTrue(rawLayer->getIconImage().isUndefined(),
@"Unsetting iconImageName should return icon-image to the default value.");
XCTAssertEqualObjects(layer.iconImageName, defaultStyleValue,
@"iconImageName should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconImageName = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconImageName = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-offset
{
XCTAssertTrue(rawLayer->getIconOffset().isUndefined(),
@"icon-offset should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconOffset;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.iconOffset = styleValue;
- mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
+ layer.iconOffset = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
@"Setting iconOffset to a constant value should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, styleValue,
+ XCTAssertEqualObjects(layer.iconOffset, constantStyleValue,
@"iconOffset should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconOffset = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconOffset = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
- @"Setting iconOffset to a function should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, styleValue,
- @"iconOffset should round-trip functions.");
-
+ @"Setting iconOffset to a camera function should update icon-offset.");
+ XCTAssertEqualObjects(layer.iconOffset, functionStyleValue,
+ @"iconOffset should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconOffset = functionStyleValue;
+
+ mbgl::style::ExponentialStops<std::array<float, 2>> exponentialStops = { {{18, { 1, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<std::array<float, 2>> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
+ @"Setting iconOffset to a source function should update icon-offset.");
+ XCTAssertEqualObjects(layer.iconOffset, functionStyleValue,
+ @"iconOffset should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconOffset = functionStyleValue;
+
+ std::map<float, std::array<float, 2>> innerStops { {18, { 1, 1 }} };
+ mbgl::style::CompositeExponentialStops<std::array<float, 2>> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<std::array<float, 2>> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
+ @"Setting iconOffset to a composite function should update icon-offset.");
+ XCTAssertEqualObjects(layer.iconOffset, functionStyleValue,
+ @"iconOffset should round-trip composite functions.");
+
+
layer.iconOffset = nil;
XCTAssertTrue(rawLayer->getIconOffset().isUndefined(),
@"Unsetting iconOffset should return icon-offset to the default value.");
XCTAssertEqualObjects(layer.iconOffset, defaultStyleValue,
@"iconOffset should return the default value after being unset.");
}
-
+
// icon-optional
{
XCTAssertTrue(rawLayer->getIconOptional().isUndefined(),
@"icon-optional should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconOptional;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.iconOptional = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.iconOptional = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconOptional(), propertyValue,
@"Setting iconOptional to a constant value should update icon-optional.");
- XCTAssertEqualObjects(layer.iconOptional, styleValue,
+ XCTAssertEqualObjects(layer.iconOptional, constantStyleValue,
@"iconOptional should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconOptional = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconOptional = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconOptional(), propertyValue,
- @"Setting iconOptional to a function should update icon-optional.");
- XCTAssertEqualObjects(layer.iconOptional, styleValue,
- @"iconOptional should round-trip functions.");
-
+ @"Setting iconOptional to a camera function should update icon-optional.");
+ XCTAssertEqualObjects(layer.iconOptional, functionStyleValue,
+ @"iconOptional should round-trip camera functions.");
+
+
+
layer.iconOptional = nil;
XCTAssertTrue(rawLayer->getIconOptional().isUndefined(),
@"Unsetting iconOptional should return icon-optional to the default value.");
XCTAssertEqualObjects(layer.iconOptional, defaultStyleValue,
@"iconOptional should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconOptional = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconOptional = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-padding
{
XCTAssertTrue(rawLayer->getIconPadding().isUndefined(),
@"icon-padding should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconPadding;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconPadding = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.iconPadding = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconPadding(), propertyValue,
@"Setting iconPadding to a constant value should update icon-padding.");
- XCTAssertEqualObjects(layer.iconPadding, styleValue,
+ XCTAssertEqualObjects(layer.iconPadding, constantStyleValue,
@"iconPadding should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconPadding = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconPadding = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconPadding(), propertyValue,
- @"Setting iconPadding to a function should update icon-padding.");
- XCTAssertEqualObjects(layer.iconPadding, styleValue,
- @"iconPadding should round-trip functions.");
-
+ @"Setting iconPadding to a camera function should update icon-padding.");
+ XCTAssertEqualObjects(layer.iconPadding, functionStyleValue,
+ @"iconPadding should round-trip camera functions.");
+
+
+
layer.iconPadding = nil;
XCTAssertTrue(rawLayer->getIconPadding().isUndefined(),
@"Unsetting iconPadding should return icon-padding to the default value.");
XCTAssertEqualObjects(layer.iconPadding, defaultStyleValue,
@"iconPadding should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-rotate
{
XCTAssertTrue(rawLayer->getIconRotate().isUndefined(),
@"icon-rotate should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconRotation;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconRotation = styleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.iconRotation = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
@"Setting iconRotation to a constant value should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, styleValue,
+ XCTAssertEqualObjects(layer.iconRotation, constantStyleValue,
@"iconRotation should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconRotation = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconRotation = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
- @"Setting iconRotation to a function should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, styleValue,
- @"iconRotation should round-trip functions.");
-
+ @"Setting iconRotation to a camera function should update icon-rotate.");
+ XCTAssertEqualObjects(layer.iconRotation, functionStyleValue,
+ @"iconRotation should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconRotation = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
+ @"Setting iconRotation to a source function should update icon-rotate.");
+ XCTAssertEqualObjects(layer.iconRotation, functionStyleValue,
+ @"iconRotation should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconRotation = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
+ @"Setting iconRotation to a composite function should update icon-rotate.");
+ XCTAssertEqualObjects(layer.iconRotation, functionStyleValue,
+ @"iconRotation should round-trip composite functions.");
+
+
layer.iconRotation = nil;
XCTAssertTrue(rawLayer->getIconRotate().isUndefined(),
@"Unsetting iconRotation should return icon-rotate to the default value.");
XCTAssertEqualObjects(layer.iconRotation, defaultStyleValue,
@"iconRotation should return the default value after being unset.");
}
-
+
// icon-rotation-alignment
{
XCTAssertTrue(rawLayer->getIconRotationAlignment().isUndefined(),
@"icon-rotation-alignment should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconRotationAlignment;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconRotationAlignment:MGLIconRotationAlignmentAuto]];
- layer.iconRotationAlignment = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconRotationAlignment:MGLIconRotationAlignmentAuto]];
+ layer.iconRotationAlignment = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getIconRotationAlignment(), propertyValue,
@"Setting iconRotationAlignment to a constant value should update icon-rotation-alignment.");
- XCTAssertEqualObjects(layer.iconRotationAlignment, styleValue,
+ XCTAssertEqualObjects(layer.iconRotationAlignment, constantStyleValue,
@"iconRotationAlignment should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconRotationAlignment = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconRotationAlignment = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::AlignmentType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconRotationAlignment(), propertyValue,
- @"Setting iconRotationAlignment to a function should update icon-rotation-alignment.");
- XCTAssertEqualObjects(layer.iconRotationAlignment, styleValue,
- @"iconRotationAlignment should round-trip functions.");
-
+ @"Setting iconRotationAlignment to a camera function should update icon-rotation-alignment.");
+ XCTAssertEqualObjects(layer.iconRotationAlignment, functionStyleValue,
+ @"iconRotationAlignment should round-trip camera functions.");
+
+
+
layer.iconRotationAlignment = nil;
XCTAssertTrue(rawLayer->getIconRotationAlignment().isUndefined(),
@"Unsetting iconRotationAlignment should return icon-rotation-alignment to the default value.");
XCTAssertEqualObjects(layer.iconRotationAlignment, defaultStyleValue,
@"iconRotationAlignment should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-size
{
XCTAssertTrue(rawLayer->getIconSize().isUndefined(),
@"icon-size should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconScale;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconScale = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.iconScale = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
@"Setting iconScale to a constant value should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, styleValue,
+ XCTAssertEqualObjects(layer.iconScale, constantStyleValue,
@"iconScale should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconScale = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconScale = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
- @"Setting iconScale to a function should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, styleValue,
- @"iconScale should round-trip functions.");
-
+ @"Setting iconScale to a camera function should update icon-size.");
+ XCTAssertEqualObjects(layer.iconScale, functionStyleValue,
+ @"iconScale should round-trip camera functions.");
+
+
+
layer.iconScale = nil;
XCTAssertTrue(rawLayer->getIconSize().isUndefined(),
@"Unsetting iconScale should return icon-size to the default value.");
XCTAssertEqualObjects(layer.iconScale, defaultStyleValue,
@"iconScale should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconScale = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconScale = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-text-fit
{
XCTAssertTrue(rawLayer->getIconTextFit().isUndefined(),
@"icon-text-fit should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTextFit;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconTextFit:MGLIconTextFitBoth]];
- layer.iconTextFit = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconTextFit:MGLIconTextFitBoth]];
+ layer.iconTextFit = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::IconTextFitType> propertyValue = { mbgl::style::IconTextFitType::Both };
XCTAssertEqual(rawLayer->getIconTextFit(), propertyValue,
@"Setting iconTextFit to a constant value should update icon-text-fit.");
- XCTAssertEqualObjects(layer.iconTextFit, styleValue,
+ XCTAssertEqualObjects(layer.iconTextFit, constantStyleValue,
@"iconTextFit should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconTextFit = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::IconTextFitType> intervalStops = { {{18, mbgl::style::IconTextFitType::Both}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::IconTextFitType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconTextFit = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::IconTextFitType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconTextFit(), propertyValue,
- @"Setting iconTextFit to a function should update icon-text-fit.");
- XCTAssertEqualObjects(layer.iconTextFit, styleValue,
- @"iconTextFit should round-trip functions.");
-
+ @"Setting iconTextFit to a camera function should update icon-text-fit.");
+ XCTAssertEqualObjects(layer.iconTextFit, functionStyleValue,
+ @"iconTextFit should round-trip camera functions.");
+
+
+
layer.iconTextFit = nil;
XCTAssertTrue(rawLayer->getIconTextFit().isUndefined(),
@"Unsetting iconTextFit should return icon-text-fit to the default value.");
XCTAssertEqualObjects(layer.iconTextFit, defaultStyleValue,
@"iconTextFit should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-text-fit-padding
{
XCTAssertTrue(rawLayer->getIconTextFitPadding().isUndefined(),
@"icon-text-fit-padding should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTextFitPadding;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(1, 1, 1, 1)]
#else
[NSValue valueWithEdgeInsets:NSEdgeInsetsMake(1, 1, 1, 1)]
#endif
];
- layer.iconTextFitPadding = styleValue;
+ layer.iconTextFitPadding = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 4>> propertyValue = { { 1, 1, 1, 1 } };
XCTAssertEqual(rawLayer->getIconTextFitPadding(), propertyValue,
@"Setting iconTextFitPadding to a constant value should update icon-text-fit-padding.");
- XCTAssertEqualObjects(layer.iconTextFitPadding, styleValue,
+ XCTAssertEqualObjects(layer.iconTextFitPadding, constantStyleValue,
@"iconTextFitPadding should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconTextFitPadding = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 4>> intervalStops = { {{18, { 1, 1, 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 4>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconTextFitPadding = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 4>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconTextFitPadding(), propertyValue,
- @"Setting iconTextFitPadding to a function should update icon-text-fit-padding.");
- XCTAssertEqualObjects(layer.iconTextFitPadding, styleValue,
- @"iconTextFitPadding should round-trip functions.");
-
+ @"Setting iconTextFitPadding to a camera function should update icon-text-fit-padding.");
+ XCTAssertEqualObjects(layer.iconTextFitPadding, functionStyleValue,
+ @"iconTextFitPadding should round-trip camera functions.");
+
+
+
layer.iconTextFitPadding = nil;
XCTAssertTrue(rawLayer->getIconTextFitPadding().isUndefined(),
@"Unsetting iconTextFitPadding should return icon-text-fit-padding to the default value.");
XCTAssertEqualObjects(layer.iconTextFitPadding, defaultStyleValue,
@"iconTextFitPadding should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-keep-upright
{
XCTAssertTrue(rawLayer->getIconKeepUpright().isUndefined(),
@"icon-keep-upright should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.keepsIconUpright;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.keepsIconUpright = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.keepsIconUpright = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getIconKeepUpright(), propertyValue,
@"Setting keepsIconUpright to a constant value should update icon-keep-upright.");
- XCTAssertEqualObjects(layer.keepsIconUpright, styleValue,
+ XCTAssertEqualObjects(layer.keepsIconUpright, constantStyleValue,
@"keepsIconUpright should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.keepsIconUpright = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.keepsIconUpright = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconKeepUpright(), propertyValue,
- @"Setting keepsIconUpright to a function should update icon-keep-upright.");
- XCTAssertEqualObjects(layer.keepsIconUpright, styleValue,
- @"keepsIconUpright should round-trip functions.");
-
+ @"Setting keepsIconUpright to a camera function should update icon-keep-upright.");
+ XCTAssertEqualObjects(layer.keepsIconUpright, functionStyleValue,
+ @"keepsIconUpright should round-trip camera functions.");
+
+
+
layer.keepsIconUpright = nil;
XCTAssertTrue(rawLayer->getIconKeepUpright().isUndefined(),
@"Unsetting keepsIconUpright should return icon-keep-upright to the default value.");
XCTAssertEqualObjects(layer.keepsIconUpright, defaultStyleValue,
@"keepsIconUpright should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-keep-upright
{
XCTAssertTrue(rawLayer->getTextKeepUpright().isUndefined(),
@"text-keep-upright should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.keepsTextUpright;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@NO];
- layer.keepsTextUpright = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@NO];
+ layer.keepsTextUpright = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { false };
XCTAssertEqual(rawLayer->getTextKeepUpright(), propertyValue,
@"Setting keepsTextUpright to a constant value should update text-keep-upright.");
- XCTAssertEqualObjects(layer.keepsTextUpright, styleValue,
+ XCTAssertEqualObjects(layer.keepsTextUpright, constantStyleValue,
@"keepsTextUpright should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.keepsTextUpright = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, false}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.keepsTextUpright = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextKeepUpright(), propertyValue,
- @"Setting keepsTextUpright to a function should update text-keep-upright.");
- XCTAssertEqualObjects(layer.keepsTextUpright, styleValue,
- @"keepsTextUpright should round-trip functions.");
-
+ @"Setting keepsTextUpright to a camera function should update text-keep-upright.");
+ XCTAssertEqualObjects(layer.keepsTextUpright, functionStyleValue,
+ @"keepsTextUpright should round-trip camera functions.");
+
+
+
layer.keepsTextUpright = nil;
XCTAssertTrue(rawLayer->getTextKeepUpright().isUndefined(),
@"Unsetting keepsTextUpright should return text-keep-upright to the default value.");
XCTAssertEqualObjects(layer.keepsTextUpright, defaultStyleValue,
@"keepsTextUpright should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-max-angle
{
XCTAssertTrue(rawLayer->getTextMaxAngle().isUndefined(),
@"text-max-angle should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.maximumTextAngle;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.maximumTextAngle = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.maximumTextAngle = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextMaxAngle(), propertyValue,
@"Setting maximumTextAngle to a constant value should update text-max-angle.");
- XCTAssertEqualObjects(layer.maximumTextAngle, styleValue,
+ XCTAssertEqualObjects(layer.maximumTextAngle, constantStyleValue,
@"maximumTextAngle should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.maximumTextAngle = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.maximumTextAngle = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextMaxAngle(), propertyValue,
- @"Setting maximumTextAngle to a function should update text-max-angle.");
- XCTAssertEqualObjects(layer.maximumTextAngle, styleValue,
- @"maximumTextAngle should round-trip functions.");
-
+ @"Setting maximumTextAngle to a camera function should update text-max-angle.");
+ XCTAssertEqualObjects(layer.maximumTextAngle, functionStyleValue,
+ @"maximumTextAngle should round-trip camera functions.");
+
+
+
layer.maximumTextAngle = nil;
XCTAssertTrue(rawLayer->getTextMaxAngle().isUndefined(),
@"Unsetting maximumTextAngle should return text-max-angle to the default value.");
XCTAssertEqualObjects(layer.maximumTextAngle, defaultStyleValue,
@"maximumTextAngle should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-max-width
{
XCTAssertTrue(rawLayer->getTextMaxWidth().isUndefined(),
@"text-max-width should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.maximumTextWidth;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.maximumTextWidth = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.maximumTextWidth = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
@"Setting maximumTextWidth to a constant value should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, styleValue,
+ XCTAssertEqualObjects(layer.maximumTextWidth, constantStyleValue,
@"maximumTextWidth should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.maximumTextWidth = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.maximumTextWidth = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
- @"Setting maximumTextWidth to a function should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, styleValue,
- @"maximumTextWidth should round-trip functions.");
-
+ @"Setting maximumTextWidth to a camera function should update text-max-width.");
+ XCTAssertEqualObjects(layer.maximumTextWidth, functionStyleValue,
+ @"maximumTextWidth should round-trip camera functions.");
+
+
+
layer.maximumTextWidth = nil;
XCTAssertTrue(rawLayer->getTextMaxWidth().isUndefined(),
@"Unsetting maximumTextWidth should return text-max-width to the default value.");
XCTAssertEqualObjects(layer.maximumTextWidth, defaultStyleValue,
@"maximumTextWidth should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.maximumTextWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.maximumTextWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// symbol-avoid-edges
{
XCTAssertTrue(rawLayer->getSymbolAvoidEdges().isUndefined(),
@"symbol-avoid-edges should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.symbolAvoidsEdges;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.symbolAvoidsEdges = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.symbolAvoidsEdges = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getSymbolAvoidEdges(), propertyValue,
@"Setting symbolAvoidsEdges to a constant value should update symbol-avoid-edges.");
- XCTAssertEqualObjects(layer.symbolAvoidsEdges, styleValue,
+ XCTAssertEqualObjects(layer.symbolAvoidsEdges, constantStyleValue,
@"symbolAvoidsEdges should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.symbolAvoidsEdges = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.symbolAvoidsEdges = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getSymbolAvoidEdges(), propertyValue,
- @"Setting symbolAvoidsEdges to a function should update symbol-avoid-edges.");
- XCTAssertEqualObjects(layer.symbolAvoidsEdges, styleValue,
- @"symbolAvoidsEdges should round-trip functions.");
-
+ @"Setting symbolAvoidsEdges to a camera function should update symbol-avoid-edges.");
+ XCTAssertEqualObjects(layer.symbolAvoidsEdges, functionStyleValue,
+ @"symbolAvoidsEdges should round-trip camera functions.");
+
+
+
layer.symbolAvoidsEdges = nil;
XCTAssertTrue(rawLayer->getSymbolAvoidEdges().isUndefined(),
@"Unsetting symbolAvoidsEdges should return symbol-avoid-edges to the default value.");
XCTAssertEqualObjects(layer.symbolAvoidsEdges, defaultStyleValue,
@"symbolAvoidsEdges should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// symbol-placement
{
XCTAssertTrue(rawLayer->getSymbolPlacement().isUndefined(),
@"symbol-placement should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.symbolPlacement;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLine]];
- layer.symbolPlacement = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLSymbolPlacement:MGLSymbolPlacementLine]];
+ layer.symbolPlacement = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::SymbolPlacementType> propertyValue = { mbgl::style::SymbolPlacementType::Line };
XCTAssertEqual(rawLayer->getSymbolPlacement(), propertyValue,
@"Setting symbolPlacement to a constant value should update symbol-placement.");
- XCTAssertEqualObjects(layer.symbolPlacement, styleValue,
+ XCTAssertEqualObjects(layer.symbolPlacement, constantStyleValue,
@"symbolPlacement should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.symbolPlacement = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::SymbolPlacementType> intervalStops = { {{18, mbgl::style::SymbolPlacementType::Line}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::SymbolPlacementType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.symbolPlacement = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::SymbolPlacementType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getSymbolPlacement(), propertyValue,
- @"Setting symbolPlacement to a function should update symbol-placement.");
- XCTAssertEqualObjects(layer.symbolPlacement, styleValue,
- @"symbolPlacement should round-trip functions.");
-
+ @"Setting symbolPlacement to a camera function should update symbol-placement.");
+ XCTAssertEqualObjects(layer.symbolPlacement, functionStyleValue,
+ @"symbolPlacement should round-trip camera functions.");
+
+
+
layer.symbolPlacement = nil;
XCTAssertTrue(rawLayer->getSymbolPlacement().isUndefined(),
@"Unsetting symbolPlacement should return symbol-placement to the default value.");
XCTAssertEqualObjects(layer.symbolPlacement, defaultStyleValue,
@"symbolPlacement should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// symbol-spacing
{
XCTAssertTrue(rawLayer->getSymbolSpacing().isUndefined(),
@"symbol-spacing should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.symbolSpacing;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.symbolSpacing = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.symbolSpacing = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getSymbolSpacing(), propertyValue,
@"Setting symbolSpacing to a constant value should update symbol-spacing.");
- XCTAssertEqualObjects(layer.symbolSpacing, styleValue,
+ XCTAssertEqualObjects(layer.symbolSpacing, constantStyleValue,
@"symbolSpacing should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.symbolSpacing = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.symbolSpacing = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getSymbolSpacing(), propertyValue,
- @"Setting symbolSpacing to a function should update symbol-spacing.");
- XCTAssertEqualObjects(layer.symbolSpacing, styleValue,
- @"symbolSpacing should round-trip functions.");
-
+ @"Setting symbolSpacing to a camera function should update symbol-spacing.");
+ XCTAssertEqualObjects(layer.symbolSpacing, functionStyleValue,
+ @"symbolSpacing should round-trip camera functions.");
+
+
+
layer.symbolSpacing = nil;
XCTAssertTrue(rawLayer->getSymbolSpacing().isUndefined(),
@"Unsetting symbolSpacing should return symbol-spacing to the default value.");
XCTAssertEqualObjects(layer.symbolSpacing, defaultStyleValue,
@"symbolSpacing should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-field
{
XCTAssertTrue(rawLayer->getTextField().isUndefined(),
@"text-field should be unset initially.");
MGLStyleValue<NSString *> *defaultStyleValue = layer.text;
-
- MGLStyleValue<NSString *> *styleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Text Field"];
- layer.text = styleValue;
- mbgl::style::PropertyValue<std::string> propertyValue = { "Text Field" };
+
+ MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Text Field"];
+ layer.text = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<std::string> propertyValue = { "Text Field" };
XCTAssertEqual(rawLayer->getTextField(), propertyValue,
@"Setting text to a constant value should update text-field.");
- XCTAssertEqualObjects(layer.text, styleValue,
+ XCTAssertEqualObjects(layer.text, constantStyleValue,
@"text should round-trip constant values.");
+
+ MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.text = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Text Field"}} };
+ propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
- styleValue = [MGLStyleValue<NSString *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.text = styleValue;
- propertyValue = { mbgl::style::Function<std::string> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextField(), propertyValue,
- @"Setting text to a function should update text-field.");
- XCTAssertEqualObjects(layer.text, styleValue,
- @"text should round-trip functions.");
-
+ @"Setting text to a camera function should update text-field.");
+ XCTAssertEqualObjects(layer.text, functionStyleValue,
+ @"text should round-trip camera functions.");
+
+
+
layer.text = nil;
XCTAssertTrue(rawLayer->getTextField().isUndefined(),
@"Unsetting text should return text-field to the default value.");
XCTAssertEqualObjects(layer.text, defaultStyleValue,
@"text should return the default value after being unset.");
}
-
+
// text-allow-overlap
{
XCTAssertTrue(rawLayer->getTextAllowOverlap().isUndefined(),
@"text-allow-overlap should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textAllowsOverlap;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.textAllowsOverlap = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.textAllowsOverlap = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getTextAllowOverlap(), propertyValue,
@"Setting textAllowsOverlap to a constant value should update text-allow-overlap.");
- XCTAssertEqualObjects(layer.textAllowsOverlap, styleValue,
+ XCTAssertEqualObjects(layer.textAllowsOverlap, constantStyleValue,
@"textAllowsOverlap should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textAllowsOverlap = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textAllowsOverlap = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextAllowOverlap(), propertyValue,
- @"Setting textAllowsOverlap to a function should update text-allow-overlap.");
- XCTAssertEqualObjects(layer.textAllowsOverlap, styleValue,
- @"textAllowsOverlap should round-trip functions.");
-
+ @"Setting textAllowsOverlap to a camera function should update text-allow-overlap.");
+ XCTAssertEqualObjects(layer.textAllowsOverlap, functionStyleValue,
+ @"textAllowsOverlap should round-trip camera functions.");
+
+
+
layer.textAllowsOverlap = nil;
XCTAssertTrue(rawLayer->getTextAllowOverlap().isUndefined(),
@"Unsetting textAllowsOverlap should return text-allow-overlap to the default value.");
XCTAssertEqualObjects(layer.textAllowsOverlap, defaultStyleValue,
@"textAllowsOverlap should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-anchor
{
XCTAssertTrue(rawLayer->getTextAnchor().isUndefined(),
@"text-anchor should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textAnchor;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextAnchor:MGLTextAnchorBottomRight]];
- layer.textAnchor = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextAnchor:MGLTextAnchorBottomRight]];
+ layer.textAnchor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TextAnchorType> propertyValue = { mbgl::style::TextAnchorType::BottomRight };
XCTAssertEqual(rawLayer->getTextAnchor(), propertyValue,
@"Setting textAnchor to a constant value should update text-anchor.");
- XCTAssertEqualObjects(layer.textAnchor, styleValue,
+ XCTAssertEqualObjects(layer.textAnchor, constantStyleValue,
@"textAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TextAnchorType> intervalStops = { {{18, mbgl::style::TextAnchorType::BottomRight}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TextAnchorType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textAnchor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TextAnchorType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextAnchor(), propertyValue,
- @"Setting textAnchor to a function should update text-anchor.");
- XCTAssertEqualObjects(layer.textAnchor, styleValue,
- @"textAnchor should round-trip functions.");
-
+ @"Setting textAnchor to a camera function should update text-anchor.");
+ XCTAssertEqualObjects(layer.textAnchor, functionStyleValue,
+ @"textAnchor should round-trip camera functions.");
+
+
+
layer.textAnchor = nil;
XCTAssertTrue(rawLayer->getTextAnchor().isUndefined(),
@"Unsetting textAnchor should return text-anchor to the default value.");
XCTAssertEqualObjects(layer.textAnchor, defaultStyleValue,
@"textAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-font
{
XCTAssertTrue(rawLayer->getTextFont().isUndefined(),
@"text-font should be unset initially.");
MGLStyleValue<NSArray<NSString *> *> *defaultStyleValue = layer.textFontNames;
-
- MGLStyleValue<NSArray<NSString *> *> *styleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithRawValue:@[@"Text Font", @"Tnof Txet"]];
- layer.textFontNames = styleValue;
+
+ MGLStyleValue<NSArray<NSString *> *> *constantStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithRawValue:@[@"Text Font", @"Tnof Txet"]];
+ layer.textFontNames = constantStyleValue;
mbgl::style::PropertyValue<std::vector<std::string>> propertyValue = { { "Text Font", "Tnof Txet" } };
XCTAssertEqual(rawLayer->getTextFont(), propertyValue,
@"Setting textFontNames to a constant value should update text-font.");
- XCTAssertEqualObjects(layer.textFontNames, styleValue,
+ XCTAssertEqualObjects(layer.textFontNames, constantStyleValue,
@"textFontNames should round-trip constant values.");
+
+ MGLStyleValue<NSArray<NSString *> *> * functionStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textFontNames = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::vector<std::string>> intervalStops = { {{18, { "Text Font", "Tnof Txet" }}} };
+ propertyValue = mbgl::style::CameraFunction<std::vector<std::string>> { intervalStops };
- styleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textFontNames = styleValue;
- propertyValue = { mbgl::style::Function<std::vector<std::string>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextFont(), propertyValue,
- @"Setting textFontNames to a function should update text-font.");
- XCTAssertEqualObjects(layer.textFontNames, styleValue,
- @"textFontNames should round-trip functions.");
-
+ @"Setting textFontNames to a camera function should update text-font.");
+ XCTAssertEqualObjects(layer.textFontNames, functionStyleValue,
+ @"textFontNames should round-trip camera functions.");
+
+
+
layer.textFontNames = nil;
XCTAssertTrue(rawLayer->getTextFont().isUndefined(),
@"Unsetting textFontNames should return text-font to the default value.");
XCTAssertEqualObjects(layer.textFontNames, defaultStyleValue,
@"textFontNames should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textFontNames = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSArray<NSString *> *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textFontNames = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-size
{
XCTAssertTrue(rawLayer->getTextSize().isUndefined(),
@"text-size should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textFontSize;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textFontSize = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textFontSize = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
@"Setting textFontSize to a constant value should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, styleValue,
+ XCTAssertEqualObjects(layer.textFontSize, constantStyleValue,
@"textFontSize should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textFontSize = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textFontSize = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
- @"Setting textFontSize to a function should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, styleValue,
- @"textFontSize should round-trip functions.");
-
+ @"Setting textFontSize to a camera function should update text-size.");
+ XCTAssertEqualObjects(layer.textFontSize, functionStyleValue,
+ @"textFontSize should round-trip camera functions.");
+
+
+
layer.textFontSize = nil;
XCTAssertTrue(rawLayer->getTextSize().isUndefined(),
@"Unsetting textFontSize should return text-size to the default value.");
XCTAssertEqualObjects(layer.textFontSize, defaultStyleValue,
@"textFontSize should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textFontSize = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textFontSize = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-ignore-placement
{
XCTAssertTrue(rawLayer->getTextIgnorePlacement().isUndefined(),
@"text-ignore-placement should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textIgnoresPlacement;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.textIgnoresPlacement = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.textIgnoresPlacement = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getTextIgnorePlacement(), propertyValue,
@"Setting textIgnoresPlacement to a constant value should update text-ignore-placement.");
- XCTAssertEqualObjects(layer.textIgnoresPlacement, styleValue,
+ XCTAssertEqualObjects(layer.textIgnoresPlacement, constantStyleValue,
@"textIgnoresPlacement should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textIgnoresPlacement = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textIgnoresPlacement = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextIgnorePlacement(), propertyValue,
- @"Setting textIgnoresPlacement to a function should update text-ignore-placement.");
- XCTAssertEqualObjects(layer.textIgnoresPlacement, styleValue,
- @"textIgnoresPlacement should round-trip functions.");
-
+ @"Setting textIgnoresPlacement to a camera function should update text-ignore-placement.");
+ XCTAssertEqualObjects(layer.textIgnoresPlacement, functionStyleValue,
+ @"textIgnoresPlacement should round-trip camera functions.");
+
+
+
layer.textIgnoresPlacement = nil;
XCTAssertTrue(rawLayer->getTextIgnorePlacement().isUndefined(),
@"Unsetting textIgnoresPlacement should return text-ignore-placement to the default value.");
XCTAssertEqualObjects(layer.textIgnoresPlacement, defaultStyleValue,
@"textIgnoresPlacement should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-justify
{
XCTAssertTrue(rawLayer->getTextJustify().isUndefined(),
@"text-justify should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textJustification;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextJustification:MGLTextJustificationRight]];
- layer.textJustification = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextJustification:MGLTextJustificationRight]];
+ layer.textJustification = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TextJustifyType> propertyValue = { mbgl::style::TextJustifyType::Right };
XCTAssertEqual(rawLayer->getTextJustify(), propertyValue,
@"Setting textJustification to a constant value should update text-justify.");
- XCTAssertEqualObjects(layer.textJustification, styleValue,
+ XCTAssertEqualObjects(layer.textJustification, constantStyleValue,
@"textJustification should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textJustification = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TextJustifyType> intervalStops = { {{18, mbgl::style::TextJustifyType::Right}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TextJustifyType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textJustification = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TextJustifyType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextJustify(), propertyValue,
- @"Setting textJustification to a function should update text-justify.");
- XCTAssertEqualObjects(layer.textJustification, styleValue,
- @"textJustification should round-trip functions.");
-
+ @"Setting textJustification to a camera function should update text-justify.");
+ XCTAssertEqualObjects(layer.textJustification, functionStyleValue,
+ @"textJustification should round-trip camera functions.");
+
+
+
layer.textJustification = nil;
XCTAssertTrue(rawLayer->getTextJustify().isUndefined(),
@"Unsetting textJustification should return text-justify to the default value.");
XCTAssertEqualObjects(layer.textJustification, defaultStyleValue,
@"textJustification should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textJustification = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textJustification = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-letter-spacing
{
XCTAssertTrue(rawLayer->getTextLetterSpacing().isUndefined(),
@"text-letter-spacing should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textLetterSpacing;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textLetterSpacing = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textLetterSpacing = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
@"Setting textLetterSpacing to a constant value should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, styleValue,
+ XCTAssertEqualObjects(layer.textLetterSpacing, constantStyleValue,
@"textLetterSpacing should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textLetterSpacing = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textLetterSpacing = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
- @"Setting textLetterSpacing to a function should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, styleValue,
- @"textLetterSpacing should round-trip functions.");
-
+ @"Setting textLetterSpacing to a camera function should update text-letter-spacing.");
+ XCTAssertEqualObjects(layer.textLetterSpacing, functionStyleValue,
+ @"textLetterSpacing should round-trip camera functions.");
+
+
+
layer.textLetterSpacing = nil;
XCTAssertTrue(rawLayer->getTextLetterSpacing().isUndefined(),
@"Unsetting textLetterSpacing should return text-letter-spacing to the default value.");
XCTAssertEqualObjects(layer.textLetterSpacing, defaultStyleValue,
@"textLetterSpacing should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textLetterSpacing = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textLetterSpacing = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-line-height
{
XCTAssertTrue(rawLayer->getTextLineHeight().isUndefined(),
@"text-line-height should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textLineHeight;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textLineHeight = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textLineHeight = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextLineHeight(), propertyValue,
@"Setting textLineHeight to a constant value should update text-line-height.");
- XCTAssertEqualObjects(layer.textLineHeight, styleValue,
+ XCTAssertEqualObjects(layer.textLineHeight, constantStyleValue,
@"textLineHeight should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textLineHeight = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textLineHeight = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextLineHeight(), propertyValue,
- @"Setting textLineHeight to a function should update text-line-height.");
- XCTAssertEqualObjects(layer.textLineHeight, styleValue,
- @"textLineHeight should round-trip functions.");
-
+ @"Setting textLineHeight to a camera function should update text-line-height.");
+ XCTAssertEqualObjects(layer.textLineHeight, functionStyleValue,
+ @"textLineHeight should round-trip camera functions.");
+
+
+
layer.textLineHeight = nil;
XCTAssertTrue(rawLayer->getTextLineHeight().isUndefined(),
@"Unsetting textLineHeight should return text-line-height to the default value.");
XCTAssertEqualObjects(layer.textLineHeight, defaultStyleValue,
@"textLineHeight should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textLineHeight = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textLineHeight = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-offset
{
XCTAssertTrue(rawLayer->getTextOffset().isUndefined(),
@"text-offset should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textOffset;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.textOffset = styleValue;
+ layer.textOffset = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
@"Setting textOffset to a constant value should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, styleValue,
+ XCTAssertEqualObjects(layer.textOffset, constantStyleValue,
@"textOffset should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textOffset = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textOffset = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
- @"Setting textOffset to a function should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, styleValue,
- @"textOffset should round-trip functions.");
-
+ @"Setting textOffset to a camera function should update text-offset.");
+ XCTAssertEqualObjects(layer.textOffset, functionStyleValue,
+ @"textOffset should round-trip camera functions.");
+
+
+
layer.textOffset = nil;
XCTAssertTrue(rawLayer->getTextOffset().isUndefined(),
@"Unsetting textOffset should return text-offset to the default value.");
XCTAssertEqualObjects(layer.textOffset, defaultStyleValue,
@"textOffset should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textOffset = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textOffset = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-optional
{
XCTAssertTrue(rawLayer->getTextOptional().isUndefined(),
@"text-optional should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textOptional;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
- layer.textOptional = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@YES];
+ layer.textOptional = constantStyleValue;
mbgl::style::PropertyValue<bool> propertyValue = { true };
XCTAssertEqual(rawLayer->getTextOptional(), propertyValue,
@"Setting textOptional to a constant value should update text-optional.");
- XCTAssertEqualObjects(layer.textOptional, styleValue,
+ XCTAssertEqualObjects(layer.textOptional, constantStyleValue,
@"textOptional should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textOptional = functionStyleValue;
+
+ mbgl::style::IntervalStops<bool> intervalStops = { {{18, true}} };
+ propertyValue = mbgl::style::CameraFunction<bool> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textOptional = styleValue;
- propertyValue = { mbgl::style::Function<bool> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextOptional(), propertyValue,
- @"Setting textOptional to a function should update text-optional.");
- XCTAssertEqualObjects(layer.textOptional, styleValue,
- @"textOptional should round-trip functions.");
-
+ @"Setting textOptional to a camera function should update text-optional.");
+ XCTAssertEqualObjects(layer.textOptional, functionStyleValue,
+ @"textOptional should round-trip camera functions.");
+
+
+
layer.textOptional = nil;
XCTAssertTrue(rawLayer->getTextOptional().isUndefined(),
@"Unsetting textOptional should return text-optional to the default value.");
XCTAssertEqualObjects(layer.textOptional, defaultStyleValue,
@"textOptional should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textOptional = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textOptional = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-padding
{
XCTAssertTrue(rawLayer->getTextPadding().isUndefined(),
@"text-padding should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textPadding;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textPadding = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textPadding = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextPadding(), propertyValue,
@"Setting textPadding to a constant value should update text-padding.");
- XCTAssertEqualObjects(layer.textPadding, styleValue,
+ XCTAssertEqualObjects(layer.textPadding, constantStyleValue,
@"textPadding should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textPadding = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textPadding = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextPadding(), propertyValue,
- @"Setting textPadding to a function should update text-padding.");
- XCTAssertEqualObjects(layer.textPadding, styleValue,
- @"textPadding should round-trip functions.");
-
+ @"Setting textPadding to a camera function should update text-padding.");
+ XCTAssertEqualObjects(layer.textPadding, functionStyleValue,
+ @"textPadding should round-trip camera functions.");
+
+
+
layer.textPadding = nil;
XCTAssertTrue(rawLayer->getTextPadding().isUndefined(),
@"Unsetting textPadding should return text-padding to the default value.");
XCTAssertEqualObjects(layer.textPadding, defaultStyleValue,
@"textPadding should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textPadding = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-pitch-alignment
{
XCTAssertTrue(rawLayer->getTextPitchAlignment().isUndefined(),
@"text-pitch-alignment should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textPitchAlignment;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextPitchAlignment:MGLTextPitchAlignmentAuto]];
- layer.textPitchAlignment = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextPitchAlignment:MGLTextPitchAlignmentAuto]];
+ layer.textPitchAlignment = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getTextPitchAlignment(), propertyValue,
@"Setting textPitchAlignment to a constant value should update text-pitch-alignment.");
- XCTAssertEqualObjects(layer.textPitchAlignment, styleValue,
+ XCTAssertEqualObjects(layer.textPitchAlignment, constantStyleValue,
@"textPitchAlignment should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textPitchAlignment = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textPitchAlignment = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::AlignmentType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextPitchAlignment(), propertyValue,
- @"Setting textPitchAlignment to a function should update text-pitch-alignment.");
- XCTAssertEqualObjects(layer.textPitchAlignment, styleValue,
- @"textPitchAlignment should round-trip functions.");
-
+ @"Setting textPitchAlignment to a camera function should update text-pitch-alignment.");
+ XCTAssertEqualObjects(layer.textPitchAlignment, functionStyleValue,
+ @"textPitchAlignment should round-trip camera functions.");
+
+
+
layer.textPitchAlignment = nil;
XCTAssertTrue(rawLayer->getTextPitchAlignment().isUndefined(),
@"Unsetting textPitchAlignment should return text-pitch-alignment to the default value.");
XCTAssertEqualObjects(layer.textPitchAlignment, defaultStyleValue,
@"textPitchAlignment should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-rotate
{
XCTAssertTrue(rawLayer->getTextRotate().isUndefined(),
@"text-rotate should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textRotation;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textRotation = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textRotation = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
@"Setting textRotation to a constant value should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, styleValue,
+ XCTAssertEqualObjects(layer.textRotation, constantStyleValue,
@"textRotation should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textRotation = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textRotation = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
- @"Setting textRotation to a function should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, styleValue,
- @"textRotation should round-trip functions.");
-
+ @"Setting textRotation to a camera function should update text-rotate.");
+ XCTAssertEqualObjects(layer.textRotation, functionStyleValue,
+ @"textRotation should round-trip camera functions.");
+
+
+
layer.textRotation = nil;
XCTAssertTrue(rawLayer->getTextRotate().isUndefined(),
@"Unsetting textRotation should return text-rotate to the default value.");
XCTAssertEqualObjects(layer.textRotation, defaultStyleValue,
@"textRotation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textRotation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-rotation-alignment
{
XCTAssertTrue(rawLayer->getTextRotationAlignment().isUndefined(),
@"text-rotation-alignment should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textRotationAlignment;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextRotationAlignment:MGLTextRotationAlignmentAuto]];
- layer.textRotationAlignment = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextRotationAlignment:MGLTextRotationAlignmentAuto]];
+ layer.textRotationAlignment = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Auto };
XCTAssertEqual(rawLayer->getTextRotationAlignment(), propertyValue,
@"Setting textRotationAlignment to a constant value should update text-rotation-alignment.");
- XCTAssertEqualObjects(layer.textRotationAlignment, styleValue,
+ XCTAssertEqualObjects(layer.textRotationAlignment, constantStyleValue,
@"textRotationAlignment should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textRotationAlignment = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Auto}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textRotationAlignment = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::AlignmentType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextRotationAlignment(), propertyValue,
- @"Setting textRotationAlignment to a function should update text-rotation-alignment.");
- XCTAssertEqualObjects(layer.textRotationAlignment, styleValue,
- @"textRotationAlignment should round-trip functions.");
-
+ @"Setting textRotationAlignment to a camera function should update text-rotation-alignment.");
+ XCTAssertEqualObjects(layer.textRotationAlignment, functionStyleValue,
+ @"textRotationAlignment should round-trip camera functions.");
+
+
+
layer.textRotationAlignment = nil;
XCTAssertTrue(rawLayer->getTextRotationAlignment().isUndefined(),
@"Unsetting textRotationAlignment should return text-rotation-alignment to the default value.");
XCTAssertEqualObjects(layer.textRotationAlignment, defaultStyleValue,
@"textRotationAlignment should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-transform
{
XCTAssertTrue(rawLayer->getTextTransform().isUndefined(),
@"text-transform should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textTransform;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextTransform:MGLTextTransformLowercase]];
- layer.textTransform = styleValue;
- mbgl::style::PropertyValue<mbgl::style::TextTransformType> propertyValue = { mbgl::style::TextTransformType::Lowercase };
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextTransform:MGLTextTransformLowercase]];
+ layer.textTransform = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::style::TextTransformType> propertyValue = { mbgl::style::TextTransformType::Lowercase };
XCTAssertEqual(rawLayer->getTextTransform(), propertyValue,
@"Setting textTransform to a constant value should update text-transform.");
- XCTAssertEqualObjects(layer.textTransform, styleValue,
+ XCTAssertEqualObjects(layer.textTransform, constantStyleValue,
@"textTransform should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textTransform = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TextTransformType> intervalStops = { {{18, mbgl::style::TextTransformType::Lowercase}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TextTransformType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textTransform = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TextTransformType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextTransform(), propertyValue,
- @"Setting textTransform to a function should update text-transform.");
- XCTAssertEqualObjects(layer.textTransform, styleValue,
- @"textTransform should round-trip functions.");
-
+ @"Setting textTransform to a camera function should update text-transform.");
+ XCTAssertEqualObjects(layer.textTransform, functionStyleValue,
+ @"textTransform should round-trip camera functions.");
+
+
+
layer.textTransform = nil;
XCTAssertTrue(rawLayer->getTextTransform().isUndefined(),
@"Unsetting textTransform should return text-transform to the default value.");
XCTAssertEqualObjects(layer.textTransform, defaultStyleValue,
@"textTransform should return the default value after being unset.");
}
-
+
// icon-color
{
XCTAssertTrue(rawLayer->getIconColor().isUndefined(),
@"icon-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.iconColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.iconColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.iconColor = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a constant value should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, styleValue,
+ XCTAssertEqualObjects(layer.iconColor, constantStyleValue,
@"iconColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
- @"Setting iconColor to a function should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, styleValue,
- @"iconColor should round-trip functions.");
-
+ @"Setting iconColor to a camera function should update icon-color.");
+ XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
+ @"iconColor should round-trip camera functions.");
+
+
+
layer.iconColor = nil;
XCTAssertTrue(rawLayer->getIconColor().isUndefined(),
@"Unsetting iconColor should return icon-color to the default value.");
XCTAssertEqualObjects(layer.iconColor, defaultStyleValue,
@"iconColor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-halo-blur
{
XCTAssertTrue(rawLayer->getIconHaloBlur().isUndefined(),
@"icon-halo-blur should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconHaloBlur;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconHaloBlur = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.iconHaloBlur = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
@"Setting iconHaloBlur to a constant value should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, styleValue,
+ XCTAssertEqualObjects(layer.iconHaloBlur, constantStyleValue,
@"iconHaloBlur should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconHaloBlur = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconHaloBlur = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
- @"Setting iconHaloBlur to a function should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, styleValue,
- @"iconHaloBlur should round-trip functions.");
-
+ @"Setting iconHaloBlur to a camera function should update icon-halo-blur.");
+ XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
+ @"iconHaloBlur should round-trip camera functions.");
+
+
+
layer.iconHaloBlur = nil;
XCTAssertTrue(rawLayer->getIconHaloBlur().isUndefined(),
@"Unsetting iconHaloBlur should return icon-halo-blur to the default value.");
XCTAssertEqualObjects(layer.iconHaloBlur, defaultStyleValue,
@"iconHaloBlur should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-halo-color
{
XCTAssertTrue(rawLayer->getIconHaloColor().isUndefined(),
@"icon-halo-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.iconHaloColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.iconHaloColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.iconHaloColor = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a constant value should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, styleValue,
+ XCTAssertEqualObjects(layer.iconHaloColor, constantStyleValue,
@"iconHaloColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconHaloColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconHaloColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
- @"Setting iconHaloColor to a function should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, styleValue,
- @"iconHaloColor should round-trip functions.");
-
+ @"Setting iconHaloColor to a camera function should update icon-halo-color.");
+ XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
+ @"iconHaloColor should round-trip camera functions.");
+
+
+
layer.iconHaloColor = nil;
XCTAssertTrue(rawLayer->getIconHaloColor().isUndefined(),
@"Unsetting iconHaloColor should return icon-halo-color to the default value.");
XCTAssertEqualObjects(layer.iconHaloColor, defaultStyleValue,
@"iconHaloColor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-halo-width
{
XCTAssertTrue(rawLayer->getIconHaloWidth().isUndefined(),
@"icon-halo-width should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconHaloWidth;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconHaloWidth = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.iconHaloWidth = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
@"Setting iconHaloWidth to a constant value should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, styleValue,
+ XCTAssertEqualObjects(layer.iconHaloWidth, constantStyleValue,
@"iconHaloWidth should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconHaloWidth = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconHaloWidth = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
- @"Setting iconHaloWidth to a function should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, styleValue,
- @"iconHaloWidth should round-trip functions.");
-
+ @"Setting iconHaloWidth to a camera function should update icon-halo-width.");
+ XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
+ @"iconHaloWidth should round-trip camera functions.");
+
+
+
layer.iconHaloWidth = nil;
XCTAssertTrue(rawLayer->getIconHaloWidth().isUndefined(),
@"Unsetting iconHaloWidth should return icon-halo-width to the default value.");
XCTAssertEqualObjects(layer.iconHaloWidth, defaultStyleValue,
@"iconHaloWidth should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-opacity
{
XCTAssertTrue(rawLayer->getIconOpacity().isUndefined(),
@"icon-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.iconOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.iconOpacity = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.iconOpacity = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
@"Setting iconOpacity to a constant value should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, styleValue,
+ XCTAssertEqualObjects(layer.iconOpacity, constantStyleValue,
@"iconOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
- @"Setting iconOpacity to a function should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, styleValue,
- @"iconOpacity should round-trip functions.");
-
+ @"Setting iconOpacity to a camera function should update icon-opacity.");
+ XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
+ @"iconOpacity should round-trip camera functions.");
+
+
+
layer.iconOpacity = nil;
XCTAssertTrue(rawLayer->getIconOpacity().isUndefined(),
@"Unsetting iconOpacity should return icon-opacity to the default value.");
XCTAssertEqualObjects(layer.iconOpacity, defaultStyleValue,
@"iconOpacity should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-translate
{
XCTAssertTrue(rawLayer->getIconTranslate().isUndefined(),
@"icon-translate should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTranslation;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.iconTranslation = styleValue;
+ layer.iconTranslation = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getIconTranslate(), propertyValue,
@"Setting iconTranslation to a constant value should update icon-translate.");
- XCTAssertEqualObjects(layer.iconTranslation, styleValue,
+ XCTAssertEqualObjects(layer.iconTranslation, constantStyleValue,
@"iconTranslation should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconTranslation = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconTranslation = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconTranslate(), propertyValue,
- @"Setting iconTranslation to a function should update icon-translate.");
- XCTAssertEqualObjects(layer.iconTranslation, styleValue,
- @"iconTranslation should round-trip functions.");
-
+ @"Setting iconTranslation to a camera function should update icon-translate.");
+ XCTAssertEqualObjects(layer.iconTranslation, functionStyleValue,
+ @"iconTranslation should round-trip camera functions.");
+
+
+
layer.iconTranslation = nil;
XCTAssertTrue(rawLayer->getIconTranslate().isUndefined(),
@"Unsetting iconTranslation should return icon-translate to the default value.");
XCTAssertEqualObjects(layer.iconTranslation, defaultStyleValue,
@"iconTranslation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// icon-translate-anchor
{
XCTAssertTrue(rawLayer->getIconTranslateAnchor().isUndefined(),
@"icon-translate-anchor should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.iconTranslationAnchor;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconTranslationAnchor:MGLIconTranslationAnchorViewport]];
- layer.iconTranslationAnchor = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLIconTranslationAnchor:MGLIconTranslationAnchorViewport]];
+ layer.iconTranslationAnchor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getIconTranslateAnchor(), propertyValue,
@"Setting iconTranslationAnchor to a constant value should update icon-translate-anchor.");
- XCTAssertEqualObjects(layer.iconTranslationAnchor, styleValue,
+ XCTAssertEqualObjects(layer.iconTranslationAnchor, constantStyleValue,
@"iconTranslationAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.iconTranslationAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.iconTranslationAnchor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TranslateAnchorType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getIconTranslateAnchor(), propertyValue,
- @"Setting iconTranslationAnchor to a function should update icon-translate-anchor.");
- XCTAssertEqualObjects(layer.iconTranslationAnchor, styleValue,
- @"iconTranslationAnchor should round-trip functions.");
-
+ @"Setting iconTranslationAnchor to a camera function should update icon-translate-anchor.");
+ XCTAssertEqualObjects(layer.iconTranslationAnchor, functionStyleValue,
+ @"iconTranslationAnchor should round-trip camera functions.");
+
+
+
layer.iconTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getIconTranslateAnchor().isUndefined(),
@"Unsetting iconTranslationAnchor should return icon-translate-anchor to the default value.");
XCTAssertEqualObjects(layer.iconTranslationAnchor, defaultStyleValue,
@"iconTranslationAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-color
{
XCTAssertTrue(rawLayer->getTextColor().isUndefined(),
@"text-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.textColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.textColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.textColor = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a constant value should update text-color.");
- XCTAssertEqualObjects(layer.textColor, styleValue,
+ XCTAssertEqualObjects(layer.textColor, constantStyleValue,
@"textColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
- @"Setting textColor to a function should update text-color.");
- XCTAssertEqualObjects(layer.textColor, styleValue,
- @"textColor should round-trip functions.");
-
+ @"Setting textColor to a camera function should update text-color.");
+ XCTAssertEqualObjects(layer.textColor, functionStyleValue,
+ @"textColor should round-trip camera functions.");
+
+
+
layer.textColor = nil;
XCTAssertTrue(rawLayer->getTextColor().isUndefined(),
@"Unsetting textColor should return text-color to the default value.");
XCTAssertEqualObjects(layer.textColor, defaultStyleValue,
@"textColor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-halo-blur
{
XCTAssertTrue(rawLayer->getTextHaloBlur().isUndefined(),
@"text-halo-blur should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textHaloBlur;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textHaloBlur = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textHaloBlur = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
@"Setting textHaloBlur to a constant value should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, styleValue,
+ XCTAssertEqualObjects(layer.textHaloBlur, constantStyleValue,
@"textHaloBlur should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textHaloBlur = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textHaloBlur = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
- @"Setting textHaloBlur to a function should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, styleValue,
- @"textHaloBlur should round-trip functions.");
-
+ @"Setting textHaloBlur to a camera function should update text-halo-blur.");
+ XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
+ @"textHaloBlur should round-trip camera functions.");
+
+
+
layer.textHaloBlur = nil;
XCTAssertTrue(rawLayer->getTextHaloBlur().isUndefined(),
@"Unsetting textHaloBlur should return text-halo-blur to the default value.");
XCTAssertEqualObjects(layer.textHaloBlur, defaultStyleValue,
@"textHaloBlur should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-halo-color
{
XCTAssertTrue(rawLayer->getTextHaloColor().isUndefined(),
@"text-halo-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.textHaloColor;
-
- MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
- layer.textHaloColor = styleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { .r = 1, .g = 0, .b = 0, .a = 1 } };
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.textHaloColor = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a constant value should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, styleValue,
+ XCTAssertEqualObjects(layer.textHaloColor, constantStyleValue,
@"textHaloColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textHaloColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
- styleValue = [MGLStyleValue<MGLColor *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textHaloColor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::Color> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
- @"Setting textHaloColor to a function should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, styleValue,
- @"textHaloColor should round-trip functions.");
-
+ @"Setting textHaloColor to a camera function should update text-halo-color.");
+ XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
+ @"textHaloColor should round-trip camera functions.");
+
+
+
layer.textHaloColor = nil;
XCTAssertTrue(rawLayer->getTextHaloColor().isUndefined(),
@"Unsetting textHaloColor should return text-halo-color to the default value.");
XCTAssertEqualObjects(layer.textHaloColor, defaultStyleValue,
@"textHaloColor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-halo-width
{
XCTAssertTrue(rawLayer->getTextHaloWidth().isUndefined(),
@"text-halo-width should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textHaloWidth;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textHaloWidth = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textHaloWidth = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
@"Setting textHaloWidth to a constant value should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, styleValue,
+ XCTAssertEqualObjects(layer.textHaloWidth, constantStyleValue,
@"textHaloWidth should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textHaloWidth = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textHaloWidth = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
- @"Setting textHaloWidth to a function should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, styleValue,
- @"textHaloWidth should round-trip functions.");
-
+ @"Setting textHaloWidth to a camera function should update text-halo-width.");
+ XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
+ @"textHaloWidth should round-trip camera functions.");
+
+
+
layer.textHaloWidth = nil;
XCTAssertTrue(rawLayer->getTextHaloWidth().isUndefined(),
@"Unsetting textHaloWidth should return text-halo-width to the default value.");
XCTAssertEqualObjects(layer.textHaloWidth, defaultStyleValue,
@"textHaloWidth should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-opacity
{
XCTAssertTrue(rawLayer->getTextOpacity().isUndefined(),
@"text-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.textOpacity;
-
- MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
- layer.textOpacity = styleValue;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.textOpacity = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
@"Setting textOpacity to a constant value should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, styleValue,
+ XCTAssertEqualObjects(layer.textOpacity, constantStyleValue,
@"textOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
- styleValue = [MGLStyleValue<NSNumber *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textOpacity = styleValue;
- propertyValue = { mbgl::style::Function<float> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
- @"Setting textOpacity to a function should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, styleValue,
- @"textOpacity should round-trip functions.");
-
+ @"Setting textOpacity to a camera function should update text-opacity.");
+ XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
+ @"textOpacity should round-trip camera functions.");
+
+
+
layer.textOpacity = nil;
XCTAssertTrue(rawLayer->getTextOpacity().isUndefined(),
@"Unsetting textOpacity should return text-opacity to the default value.");
XCTAssertEqualObjects(layer.textOpacity, defaultStyleValue,
@"textOpacity should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-translate
{
XCTAssertTrue(rawLayer->getTextTranslate().isUndefined(),
@"text-translate should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textTranslation;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
#if TARGET_OS_IPHONE
[NSValue valueWithCGVector:CGVectorMake(1, 1)]
#else
[NSValue valueWithMGLVector:CGVectorMake(1, -1)]
#endif
];
- layer.textTranslation = styleValue;
+ layer.textTranslation = constantStyleValue;
mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
XCTAssertEqual(rawLayer->getTextTranslate(), propertyValue,
@"Setting textTranslation to a constant value should update text-translate.");
- XCTAssertEqualObjects(layer.textTranslation, styleValue,
+ XCTAssertEqualObjects(layer.textTranslation, constantStyleValue,
@"textTranslation should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textTranslation = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textTranslation = styleValue;
- propertyValue = { mbgl::style::Function<std::array<float, 2>> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextTranslate(), propertyValue,
- @"Setting textTranslation to a function should update text-translate.");
- XCTAssertEqualObjects(layer.textTranslation, styleValue,
- @"textTranslation should round-trip functions.");
-
+ @"Setting textTranslation to a camera function should update text-translate.");
+ XCTAssertEqualObjects(layer.textTranslation, functionStyleValue,
+ @"textTranslation should round-trip camera functions.");
+
+
+
layer.textTranslation = nil;
XCTAssertTrue(rawLayer->getTextTranslate().isUndefined(),
@"Unsetting textTranslation should return text-translate to the default value.");
XCTAssertEqualObjects(layer.textTranslation, defaultStyleValue,
@"textTranslation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
-
+
// text-translate-anchor
{
XCTAssertTrue(rawLayer->getTextTranslateAnchor().isUndefined(),
@"text-translate-anchor should be unset initially.");
MGLStyleValue<NSValue *> *defaultStyleValue = layer.textTranslationAnchor;
-
- MGLStyleValue<NSValue *> *styleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextTranslationAnchor:MGLTextTranslationAnchorViewport]];
- layer.textTranslationAnchor = styleValue;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLTextTranslationAnchor:MGLTextTranslationAnchorViewport]];
+ layer.textTranslationAnchor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
XCTAssertEqual(rawLayer->getTextTranslateAnchor(), propertyValue,
@"Setting textTranslationAnchor to a constant value should update text-translate-anchor.");
- XCTAssertEqualObjects(layer.textTranslationAnchor, styleValue,
+ XCTAssertEqualObjects(layer.textTranslationAnchor, constantStyleValue,
@"textTranslationAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.textTranslationAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
- styleValue = [MGLStyleValue<NSValue *> valueWithStops:@{
- @18: styleValue,
- }];
- layer.textTranslationAnchor = styleValue;
- propertyValue = { mbgl::style::Function<mbgl::style::TranslateAnchorType> {
- {{ 18, propertyValue.asConstant() }},
- 1,
- }};
XCTAssertEqual(rawLayer->getTextTranslateAnchor(), propertyValue,
- @"Setting textTranslationAnchor to a function should update text-translate-anchor.");
- XCTAssertEqualObjects(layer.textTranslationAnchor, styleValue,
- @"textTranslationAnchor should round-trip functions.");
-
+ @"Setting textTranslationAnchor to a camera function should update text-translate-anchor.");
+ XCTAssertEqualObjects(layer.textTranslationAnchor, functionStyleValue,
+ @"textTranslationAnchor should round-trip camera functions.");
+
+
+
layer.textTranslationAnchor = nil;
XCTAssertTrue(rawLayer->getTextTranslateAnchor().isUndefined(),
@"Unsetting textTranslationAnchor should return text-translate-anchor to the default value.");
XCTAssertEqualObjects(layer.textTranslationAnchor, defaultStyleValue,
@"textTranslationAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}
diff --git a/platform/darwin/test/MGLTileSetTests.mm b/platform/darwin/test/MGLTileSetTests.mm
index 06901a0e96..40eab5f974 100644
--- a/platform/darwin/test/MGLTileSetTests.mm
+++ b/platform/darwin/test/MGLTileSetTests.mm
@@ -15,40 +15,40 @@
// a tile set that provides an mbgl tile set
NSArray *tileURLTemplates = @[@"tile.1", @"tile.2", @"tile.3"];
mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, nil);
-
+
// has the correct URL templates
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(tileSet.scheme, mbgl::Tileset::Scheme::XYZ);
-
+
// when the tile set has no min or max zoom level set
// the mbgl object has default values for min and max zoom level
XCTAssertEqual(tileSet.zoomRange.min, 0);
XCTAssertEqual(tileSet.zoomRange.max, 22);
-
+
// when the tile set has min and/or max zoom level set
tileSet = MGLTileSetFromTileURLTemplates(@[@"tile.1"], @{
MGLTileSourceOptionMinimumZoomLevel: @1,
MGLTileSourceOptionMaximumZoomLevel: @2,
});
-
+
// the mbgl object reflects the set values for min and max zoom level
XCTAssertEqual(tileSet.zoomRange.min, 1);
XCTAssertEqual(tileSet.zoomRange.max, 2);
-
+
// when the tile set has an attribution
NSString *attribution = @"my tileset © ©️🎈";
tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
MGLTileSourceOptionAttributionHTMLString: attribution,
});
-
+
// the attribution is reflected by the mbgl tileset
XCTAssertEqual(tileSet.attribution, attribution.UTF8String);
-
+
// when the tile set has attribution infos
MGLAttributionInfo *mapboxInfo = [[MGLAttributionInfo alloc] initWithTitle:[[NSAttributedString alloc] initWithString:@"Mapbox"]
URL:[NSURL URLWithString:@"https://www.mapbox.com/"]];
@@ -59,7 +59,7 @@
tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
MGLTileSourceOptionAttributionInfos: @[mapboxInfo, glInfo],
});
-
+
// the attribution is reflected by the mbgl tileset
#if TARGET_OS_IPHONE
NSString *html = (@"<font style=\"font-family: 'Helvetica'; font-weight: normal; font-style: normal; font-size: 12.00pt\">"
@@ -71,21 +71,21 @@
@"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica; background-color: #ff2600\">GL</font>\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.scheme, mbgl::Tileset::Scheme::TMS);
-
+
// when the tile coordinate system is changed using an NSValue
MGLTileCoordinateSystem tms = MGLTileCoordinateSystemTMS;
tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
MGLTileSourceOptionTileCoordinateSystem: [NSValue value:&tms withObjCType:@encode(MGLTileCoordinateSystem)],
});
-
+
// the scheme is reflected by the mbgl tileset
XCTAssertEqual(tileSet.scheme, mbgl::Tileset::Scheme::TMS);
}
diff --git a/platform/darwin/test/MGLVersionNumber.m b/platform/darwin/test/MGLVersionNumber.m
new file mode 100644
index 0000000000..fae08a087d
--- /dev/null
+++ b/platform/darwin/test/MGLVersionNumber.m
@@ -0,0 +1,15 @@
+#import <Mapbox/Mapbox.h>
+
+#import <XCTest/XCTest.h>
+
+@interface MGLVersionTests : XCTestCase
+
+@end
+
+@implementation MGLVersionTests
+
+- (void)testVersionNumber {
+ XCTAssertEqual(1, MapboxVersionNumber);
+}
+
+@end