summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt38
-rw-r--r--platform/darwin/src/MGLNetworkConfiguration.m42
-rw-r--r--platform/darwin/src/MGLOfflineRegion.h2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.h87
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm106
-rw-r--r--platform/darwin/src/MGLShapeOfflineRegion.mm2
-rw-r--r--platform/darwin/src/MGLTilePyramidOfflineRegion.mm2
-rw-r--r--platform/darwin/src/MGLTypes.h4
-rw-r--r--platform/darwin/test/MGLOfflineRegionTests.m24
-rw-r--r--platform/darwin/test/MGLOfflineStorageTests.mm62
-rw-r--r--platform/ios/CHANGELOG.md3
-rw-r--r--platform/ios/app/MBXOfflinePacksTableViewController.m19
-rw-r--r--platform/ios/app/Main.storyboard53
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj4
-rw-r--r--platform/ios/src/MGLMapView.mm12
-rw-r--r--platform/ios/test/MGLNetworkConfigurationTests.m43
-rw-r--r--platform/macos/CHANGELOG.md4
-rw-r--r--platform/macos/app/MapDocument.m4
-rw-r--r--platform/node/CHANGELOG.md7
20 files changed, 449 insertions, 71 deletions
diff --git a/package.json b/package.json
index 991b115446..e239c60864 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@mapbox/mapbox-gl-native",
- "version": "4.0.0",
+ "version": "4.2.0",
"description": "Renders map tiles with Mapbox GL",
"keywords": [
"mapbox",
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt
index e295b5b10b..5044c077a8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotterTest.kt
@@ -2,25 +2,51 @@ package com.mapbox.mapboxsdk.snapshotter
import android.support.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4
-import com.mapbox.mapboxsdk.testapp.activity.snapshot.MapSnapshotterMarkerActivity
+import com.mapbox.mapboxsdk.camera.CameraPosition
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
+import junit.framework.Assert.assertNotNull
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
/**
- * Integration test that validates if a snapshot is created with MapSnapshotterMarkerActivity
+ * Integration test that validates if a snapshotter creation
*/
@RunWith(AndroidJUnit4::class)
class MapSnapshotterTest {
@Rule
@JvmField
- var rule = ActivityTestRule(MapSnapshotterMarkerActivity::class.java)
+ var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
- @Test(timeout = 10000)
+ private val countDownLatch = CountDownLatch(1)
+
+ @Test
fun mapSnapshotter() {
- while (rule.activity.mapSnapshot == null) {
- Thread.sleep(250)
+ rule.activity.runOnUiThread {
+ val options = MapSnapshotter.Options(512, 512)
+ .withPixelRatio(1.0f)
+ .withStyle(Style.SATELLITE_STREETS)
+ .withCameraPosition(
+ CameraPosition.Builder()
+ .zoom(12.0)
+ .target(LatLng(51.145495, 5.742234))
+ .build()
+ )
+ val mapSnapshotter = MapSnapshotter(rule.activity, options)
+ mapSnapshotter.start {
+ assertNotNull(it)
+ assertNotNull(it.bitmap)
+ countDownLatch.countDown()
+ }
+ }
+ if (!countDownLatch.await(30, TimeUnit.SECONDS)) {
+ throw TimeoutException()
}
}
} \ No newline at end of file
diff --git a/platform/darwin/src/MGLNetworkConfiguration.m b/platform/darwin/src/MGLNetworkConfiguration.m
index 40993c97b5..0e5046e7a3 100644
--- a/platform/darwin/src/MGLNetworkConfiguration.m
+++ b/platform/darwin/src/MGLNetworkConfiguration.m
@@ -11,6 +11,7 @@ NSString * const kMGLDownloadPerformanceEvent = @"mobile.performance_trace";
@property (strong) NSURLSessionConfiguration *sessionConfig;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSDictionary*> *events;
@property (nonatomic, weak) id<MGLNetworkConfigurationMetricsDelegate> metricsDelegate;
+@property (nonatomic) dispatch_queue_t eventsQueue;
@end
@@ -20,6 +21,7 @@ NSString * const kMGLDownloadPerformanceEvent = @"mobile.performance_trace";
if (self = [super init]) {
self.sessionConfiguration = nil;
_events = [NSMutableDictionary dictionary];
+ _eventsQueue = dispatch_queue_create("com.mapbox.network-configuration", DISPATCH_QUEUE_CONCURRENT);
}
return self;
@@ -65,8 +67,9 @@ NSString * const kMGLDownloadPerformanceEvent = @"mobile.performance_trace";
}
- (void)startDownloadEvent:(NSString *)urlString type:(NSString *)resourceType {
- if (urlString && ![self.events objectForKey:urlString]) {
- [self.events setObject:@{ MGLStartTime: [NSDate date], MGLResourceType: resourceType } forKey:urlString];
+ if (urlString && ![self eventDictionaryForKey:urlString]) {
+ NSDate *startDate = [NSDate date];
+ [self setEventDictionary:@{ MGLStartTime: startDate, MGLResourceType: resourceType } forKey:urlString];
}
}
@@ -82,10 +85,13 @@ NSString * const kMGLDownloadPerformanceEvent = @"mobile.performance_trace";
{
if ([response isKindOfClass:[NSURLResponse class]]) {
NSString *urlString = response.URL.relativePath;
- if (urlString && [self.events objectForKey:urlString]) {
+ if (urlString && [self eventDictionaryForKey:urlString]) {
NSDictionary *eventAttributes = [self eventAttributesForURL:response withAction:action];
- [self.metricsDelegate networkConfiguration:self didGenerateMetricEvent:eventAttributes];
- [self.events removeObjectForKey:urlString];
+ [self removeEventDictionaryForKey:urlString];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.metricsDelegate networkConfiguration:self didGenerateMetricEvent:eventAttributes];
+ });
}
}
@@ -94,7 +100,7 @@ NSString * const kMGLDownloadPerformanceEvent = @"mobile.performance_trace";
- (NSDictionary *)eventAttributesForURL:(NSURLResponse *)response withAction:(NSString *)action
{
NSString *urlString = response.URL.relativePath;
- NSDictionary *parameters = [self.events objectForKey:urlString];
+ NSDictionary *parameters = [self eventDictionaryForKey:urlString];
NSDate *startDate = [parameters objectForKey:MGLStartTime];
NSDate *endDate = [NSDate date];
NSTimeInterval elapsedTime = [endDate timeIntervalSinceDate:startDate];
@@ -129,4 +135,28 @@ NSString * const kMGLDownloadPerformanceEvent = @"mobile.performance_trace";
};
}
+#pragma mark - Events dictionary access
+
+- (nullable NSDictionary*)eventDictionaryForKey:(nonnull NSString*)key {
+ __block NSDictionary *dictionary;
+
+ dispatch_sync(self.eventsQueue, ^{
+ dictionary = [self.events objectForKey:key];
+ });
+
+ return dictionary;
+}
+
+- (void)setEventDictionary:(nonnull NSDictionary*)dictionary forKey:(nonnull NSString*)key {
+ dispatch_barrier_async(self.eventsQueue, ^{
+ [self.events setObject:dictionary forKey:key];
+ });
+}
+
+- (void)removeEventDictionaryForKey:(nonnull NSString*)key {
+ dispatch_barrier_async(self.eventsQueue, ^{
+ [self.events removeObjectForKey:key];
+ });
+}
+
@end
diff --git a/platform/darwin/src/MGLOfflineRegion.h b/platform/darwin/src/MGLOfflineRegion.h
index 0bb1981d61..f873424c93 100644
--- a/platform/darwin/src/MGLOfflineRegion.h
+++ b/platform/darwin/src/MGLOfflineRegion.h
@@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
See `MGLIdeographicFontFamilyName` setting. Also, for regions outside of
China, Japan, and Korea, these glyphs will rarely appear for non-CJK users.
- By default, this property is set to `YES`, so that the offline pack will
+ By default, this property is set to `NO`, so that the offline pack will
include ideographic glyphs.
*/
@property (nonatomic) BOOL includesIdeographicGlyphs;
diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h
index b48f2ebf2c..c6a51df80c 100644
--- a/platform/darwin/src/MGLOfflineStorage.h
+++ b/platform/darwin/src/MGLOfflineStorage.h
@@ -171,9 +171,9 @@ typedef NS_ENUM(NSUInteger, MGLResourceKind) {
/**
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.
+ packs and ambient caching. 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.
#### Related examples
See the <a href="https://docs.mapbox.com/ios/maps/examples/offline-pack/">
@@ -304,6 +304,21 @@ MGL_EXPORT
- (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(nullable MGLOfflinePackRemovalCompletionHandler)completion;
/**
+ Invalidates the specified offline pack. This method checks that the tiles
+ in the specified offline pack match those from the server. Local tiles that
+ do not match the latest version on the server are updated.
+
+ This is more efficient than deleting the offline pack and downloading it
+ again. If the data stored locally matches that on the server, new data will
+ not be downloaded.
+
+ @param pack The offline pack to be invalidated.
+ @param completion The completion handler to call once the pack has been
+ removed. This handler is executed asynchronously on the main queue.
+ */
+
+- (void)invalidatePack:(MGLOfflinePack *)pack withCompletionHandler:(void (^)(NSError * _Nullable))completion;
+/**
Forcibly, asynchronously reloads the `packs` property. At some point after this
method is called, the pointer values of the `MGLOfflinePack` objects in the
`packs` property change, even if the underlying data for these packs has not
@@ -341,6 +356,72 @@ MGL_EXPORT
*/
@property (nonatomic, readonly) unsigned long long countOfBytesCompleted;
+
+#pragma mark - Managing Ambient Cache
+
+/**
+ Sets the maximum ambient cache size in megabytes. The default maximum cache
+ size is 50 MB. To disable ambient caching, set the maximum ambient cache size
+ to `0`. Setting the maximum ambient cache size does not impact the maximum size
+ of offline packs.
+
+ While this method does not limit the space available to offline packs,
+ data in offline packs count towards this limit. If the maximum ambient
+ cache size is set to 30 MB and 20 MB of offline packs are downloaded,
+ there may be only 10 MB reserved for the ambient cache.
+
+ This method should be called before the map and map style have been loaded.
+
+ This method is potentially expensive, as the database will trim cached data
+ in order to prevent the ambient cache from being larger than the
+ specified amount.
+
+ @param cacheSize The maximum size in bytes for the ambient cache.
+ @param completion The completion handler to call once the maximum ambient cache size
+ has been set. This handler is executed synchronously on the main queue.
+ */
+
+- (void)setMaximumAmbientCacheSize:(NSUInteger)cacheSize withCompletionHandler:(void (^)(NSError *_Nullable error))completion;
+
+/**
+ Invalidates the ambient cache. This method checks that the tiles in the
+ ambient cache match those from the server. If the local tiles do not match
+ those on the server, they are re-downloaded.
+
+ This is recommended over clearing the cache or resetting the database
+ because valid local tiles will not be downloaded again.
+
+ Resources shared with offline packs will not be affected by this method.
+
+ @param completion The completion handler to call once the ambient cache has
+ been revalidated. This handler is executed asynchronously on the main queue.
+ */
+
+- (void)invalidateAmbientCacheWithCompletionHandler:(void (^)(NSError *_Nullable error))completion;
+
+/**
+ Clears the ambient cache by deleting resources. This method does not
+ affect resources shared with offline regions.
+
+ @param completion The completion handler to call once resources from
+ the ambient cache have been cleared. This handler is executed
+ asynchronously on the main queue.
+ */
+
+- (void)clearAmbientCacheWithCompletionHandler:(void (^)(NSError *_Nullable error))completion;
+
+/**
+ Deletes the existing database, which includes both the ambient cache and offline packs,
+ then reinitializes it.
+
+ You typically do not need to call this method.
+
+ @param completion The completion handler to call once the pack has database has
+ been reset. This handler is executed asynchronously on the main queue.
+ */
+
+- (void)resetDatabaseWithCompletionHandler:(void (^)(NSError *_Nullable error))completion;
+
/*
Inserts the provided resource into the ambient cache.
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 6effd8c3ce..93f986a518 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -48,7 +48,6 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
@property (nonatomic) std::shared_ptr<mbgl::DefaultFileSource> mbglFileSource;
@property (nonatomic) std::string mbglCachePath;
@property (nonatomic, getter=isPaused) BOOL paused;
-
@end
@implementation MGLOfflineStorage {
@@ -341,10 +340,11 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
NSMutableArray *packs;
if (!result) {
NSString *description = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"ADD_FILE_CONTENTS_FAILED_DESC", @"Foundation", nil, @"Unable to add offline packs from the file at %@.", @"User-friendly error description"), filePath];
- error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
- NSLocalizedDescriptionKey: description,
- NSLocalizedFailureReasonErrorKey: @(mbgl::util::toString(result.error()).c_str())
- }];
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed
+ userInfo:@{
+ NSLocalizedDescriptionKey: description,
+ NSLocalizedFailureReasonErrorKey: @(mbgl::util::toString(result.error()).c_str())
+ }];
} else {
auto& regions = result.value();
packs = [NSMutableArray arrayWithCapacity:regions.size()];
@@ -401,7 +401,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
NSError *error;
if (!mbglOfflineRegion) {
NSString *errorDescription = @(mbgl::util::toString(mbglOfflineRegion.error()).c_str());
- error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:errorDescription ? @{
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed userInfo:errorDescription ? @{
NSLocalizedDescriptionKey: errorDescription,
} : nil];
}
@@ -431,11 +431,10 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
completion(nil);
return;
}
-
_mbglFileSource->deleteOfflineRegion(std::move(*mbglOfflineRegion), [&, completion](std::exception_ptr exception) {
NSError *error;
if (exception) {
- error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed userInfo:@{
NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
}];
}
@@ -445,6 +444,29 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
});
}
});
+
+}
+
+- (void)invalidatePack:(MGLOfflinePack *)pack withCompletionHandler:(void (^)(NSError * _Nullable))completion {
+ mbgl::OfflineRegion& region = *pack.mbglOfflineRegion;
+ NSError *error;
+ if (!pack.mbglOfflineRegion) {
+ completion(nil);
+ return;
+ }
+
+ _mbglFileSource->invalidateOfflineRegion(region, [&](std::exception_ptr exception) {
+ if (exception) {
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed userInfo:@{
+ NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
+ }];
+ }
+ });
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), [&, completion, error](void) {
+ completion(error);
+ });
+ }
}
- (void)reloadPacks {
@@ -462,7 +484,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
NSError *error;
NSMutableArray *packs;
if (!result) {
- error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeUnknown userInfo:@{
NSLocalizedDescriptionKey: @(mbgl::util::toString(result.error()).c_str()),
}];
} else {
@@ -486,6 +508,72 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio
_mbglFileSource->setOfflineMapboxTileCountLimit(maximumCount);
}
+#pragma mark - Ambient Cache management
+
+- (void)setMaximumAmbientCacheSize:(NSUInteger)cacheSize withCompletionHandler:(void (^)(NSError * _Nullable))completion {
+ _mbglFileSource->setMaximumAmbientCacheSize(cacheSize, [&, completion](std::exception_ptr exception) {
+ NSError *error;
+ if (completion) {
+ if (exception) {
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed userInfo:@{
+ NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
+ }];
+ }
+ dispatch_sync(dispatch_get_main_queue(), ^ {
+ completion(error);
+ });
+ }
+ });
+}
+
+- (void)invalidateAmbientCacheWithCompletionHandler:(void (^)(NSError *_Nullable))completion {
+ _mbglFileSource->invalidateAmbientCache([&, completion](std::exception_ptr exception){
+ NSError *error;
+ if (completion) {
+ if (exception) {
+ // Convert std::exception_ptr to an NSError.
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed userInfo:@{
+ NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
+ }];
+ }
+ dispatch_async(dispatch_get_main_queue(), ^ {
+ completion(error);
+ });
+ }
+ });
+}
+
+- (void)clearAmbientCacheWithCompletionHandler:(void (^)(NSError *_Nullable error))completion {
+ _mbglFileSource->clearAmbientCache([&, completion](std::exception_ptr exception){
+ NSError *error;
+ if (completion) {
+ if (exception) {
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeModifyingOfflineStorageFailed userInfo:@{
+ NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
+ }];
+ }
+ dispatch_async(dispatch_get_main_queue(), [&, completion, error](void) {
+ completion(error);
+ });
+ }
+ });
+}
+
+- (void)resetDatabaseWithCompletionHandler:(void (^)(NSError *_Nullable error))completion {
+ _mbglFileSource->resetDatabase([&, completion](std::exception_ptr exception) {
+ NSError *error;
+ if (completion) {
+ if (exception) {
+ error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeUnknown userInfo:@{
+ NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
+ }];
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(error);
+ });
+ }
+ });
+}
#pragma mark -
- (unsigned long long)countOfBytesCompleted {
diff --git a/platform/darwin/src/MGLShapeOfflineRegion.mm b/platform/darwin/src/MGLShapeOfflineRegion.mm
index 25b6b8e166..b4f4b5e92a 100644
--- a/platform/darwin/src/MGLShapeOfflineRegion.mm
+++ b/platform/darwin/src/MGLShapeOfflineRegion.mm
@@ -72,7 +72,7 @@
_shape = shape;
_minimumZoomLevel = minimumZoomLevel;
_maximumZoomLevel = maximumZoomLevel;
- _includesIdeographicGlyphs = YES;
+ _includesIdeographicGlyphs = NO;
}
return self;
}
diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm
index a398d6baa4..73fcaa91d8 100644
--- a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm
+++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm
@@ -68,7 +68,7 @@
_bounds = bounds;
_minimumZoomLevel = minimumZoomLevel;
_maximumZoomLevel = maximumZoomLevel;
- _includesIdeographicGlyphs = YES;
+ _includesIdeographicGlyphs = NO;
}
return self;
}
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index b8354d2e83..7e0dd27141 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -53,7 +53,9 @@ typedef NS_ENUM(NSInteger, MGLErrorCode) {
/** Source is in use and cannot be removed */
MGLErrorCodeSourceIsInUseCannotRemove = 7,
/** Source is in use and cannot be removed */
- MGLErrorCodeSourceIdentifierMismatch = 8
+ MGLErrorCodeSourceIdentifierMismatch = 8,
+ /** An error occurred while modifying the offline storage database */
+ MGLErrorCodeModifyingOfflineStorageFailed = 9
};
/** Options for enabling debugging features in an `MGLMapView` instance. */
diff --git a/platform/darwin/test/MGLOfflineRegionTests.m b/platform/darwin/test/MGLOfflineRegionTests.m
index 4d5767a8d2..0af9ebb5fa 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, MGLInvalidStyleURLException, @"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, copy.minimumZoomLevel, @"Minimum zoom level has changed.");
@@ -48,4 +48,24 @@
XCTAssertEqual(original.includesIdeographicGlyphs, copy.includesIdeographicGlyphs, @"Include ideographs has changed.");
}
+- (void)testIncludesIdeographicGlyphsByDefault {
+
+ // Tile pyramid offline region
+ {
+ MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(kCLLocationCoordinate2DInvalid, kCLLocationCoordinate2DInvalid);
+ MGLTilePyramidOfflineRegion *tilePyramidOfflineRegion = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:[MGLStyle lightStyleURLWithVersion:MGLStyleDefaultVersion] bounds:bounds fromZoomLevel:5 toZoomLevel:10];
+ XCTAssertFalse(tilePyramidOfflineRegion.includesIdeographicGlyphs, @"tile pyramid offline region should not include ideographic glyphs");
+ }
+
+ // Shape offline region
+ {
+ NSString *geojson = @"{\"type\": \"Point\", \"coordinates\": [-3.8671874999999996, 52.482780222078226] }";
+ NSError *error;
+ MGLShape *shape = [MGLShape shapeWithData: [geojson dataUsingEncoding:NSUTF8StringEncoding] encoding: NSUTF8StringEncoding error:&error];
+ XCTAssertNil(error);
+ MGLShapeOfflineRegion *shapeOfflineRegion = [[MGLShapeOfflineRegion alloc] initWithStyleURL:[MGLStyle lightStyleURLWithVersion:MGLStyleDefaultVersion] shape:shape fromZoomLevel:5 toZoomLevel:10];
+ XCTAssertFalse(shapeOfflineRegion.includesIdeographicGlyphs, @"tile pyramid offline region should not include ideographic glyphs");
+ }
+}
+
@end
diff --git a/platform/darwin/test/MGLOfflineStorageTests.mm b/platform/darwin/test/MGLOfflineStorageTests.mm
index 5551d8889b..ee4bcc2c65 100644
--- a/platform/darwin/test/MGLOfflineStorageTests.mm
+++ b/platform/darwin/test/MGLOfflineStorageTests.mm
@@ -201,6 +201,68 @@
pack = nil;
}
+- (void)testInvalidatePack {
+ XCTestExpectation *expectation = [self expectationWithDescription:@"Expect offline pack to be invalidated without an error."];
+ MGLCoordinateBounds bounds = {
+ { .latitude = 48.8660, .longitude = 2.3306 },
+ { .latitude = 48.8603, .longitude = 2.3213 },
+ };
+
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:styleURL bounds:bounds fromZoomLevel:10 toZoomLevel:11];
+
+ NSString *nameKey = @"Name";
+ NSString *name = @"Paris square";
+
+ NSData *context = [NSKeyedArchiver archivedDataWithRootObject:@{nameKey: name}];
+ [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable pack, NSError * _Nullable error) {
+ XCTAssertNotNil(pack);
+ [[MGLOfflineStorage sharedOfflineStorage] invalidatePack:pack withCompletionHandler:^(NSError * _Nullable) {
+ XCTAssertNotNil(pack);
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ }];
+ [self waitForExpectationsWithTimeout:10 handler:nil];
+}
+
+- (void)testSetMaximumAmbientCache {
+ XCTestExpectation *expectation = [self expectationWithDescription:@"Expect maximum cache size to be raised without an error."];
+ [[MGLOfflineStorage sharedOfflineStorage] setMaximumAmbientCacheSize:0 withCompletionHandler:^(NSError * _Nullable error) {
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+
+ [self waitForExpectationsWithTimeout:10 handler:nil];
+}
+
+- (void)testInvalidateAmbientCache {
+ XCTestExpectation *expectation = [self expectationWithDescription:@"Expect cache to be invalidated without an error."];
+ [[MGLOfflineStorage sharedOfflineStorage] invalidateAmbientCacheWithCompletionHandler:^(NSError * _Nullable error) {
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:10 handler:nil];
+}
+
+- (void)testClearCache {
+ XCTestExpectation *expectation = [self expectationWithDescription:@"Expect cache to be cleared without an error."];
+ [[MGLOfflineStorage sharedOfflineStorage] clearAmbientCacheWithCompletionHandler:^(NSError * _Nullable error) {
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:10 handler:nil];
+}
+
+- (void)testResetDatabase {
+ XCTestExpectation *expectation = [self expectationWithDescription:@"Expect database to be reset without an error."];
+ [[MGLOfflineStorage sharedOfflineStorage] resetDatabaseWithCompletionHandler:^(NSError * _Nullable error) {
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:10 handler:nil];
+}
+
- (void)testBackupExclusion {
NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index cdb853ebb6..ed815cc141 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -10,6 +10,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
### Other changes
* Updated "map ID" to the more accurate term "tileset ID" in documentation; updated "style's Map ID" to the more accurate term "style URL". ([#15116](https://github.com/mapbox/mapbox-gl-native/pull/15116))
+* Ideographic glyphs from Chinese, Japanese, and Korean are no longer downloaded by default as part of offline packs; they are instead rendered on-device, saving bandwidth and storage while improving performance. ([#14176](https://github.com/mapbox/mapbox-gl-native/pull/14176))
## 5.2.0
@@ -44,6 +45,8 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Deprecated variants of the above methods without completion handlers. ([#14959](https://github.com/mapbox/mapbox-gl-native/pull/14959))
* Fixed an issue where the two-finger tilt gesture would continue after lifting one finger. ([#14969](https://github.com/mapbox/mapbox-gl-native/pull/14969))
* Added `MGLMapView.compassView.visibility` and `MGLOrnamentVisibility` to allow configuration of compass visibility behavior. ([#15055](https://github.com/mapbox/mapbox-gl-native/pull/15055))
+* Fixed a bug where using the pinch gesture could result in an incorrect map center coordinate. ([#15097](https://github.com/mapbox/mapbox-gl-native/pull/15097))
+* Fixed a crash during network access. ([#15113](https://github.com/mapbox/mapbox-gl-native/pull/15113))
## 5.1.0 - June 19, 2019
diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m
index e237df4019..90497ca939 100644
--- a/platform/ios/app/MBXOfflinePacksTableViewController.m
+++ b/platform/ios/app/MBXOfflinePacksTableViewController.m
@@ -103,8 +103,10 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac
}
MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:mapView.styleURL bounds:mapView.visibleCoordinateBounds fromZoomLevel:mapView.zoomLevel toZoomLevel:mapView.maximumZoomLevel];
- BOOL hasIdeographicFontFamilyName = !![[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLIdeographicFontFamilyName"];
- region.includesIdeographicGlyphs = hasIdeographicFontFamilyName;
+ id ideographicFontFamilyName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLIdeographicFontFamilyName"];
+ if([ideographicFontFamilyName isKindOfClass:[NSNumber class]] && ![ideographicFontFamilyName boolValue]){
+ region.includesIdeographicGlyphs = YES;
+ }
NSData *context = [NSKeyedArchiver archivedDataWithRootObject:@{
MBXOfflinePackContextNameKey: name,
}];
@@ -126,6 +128,19 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac
[self presentViewController:alertController animated:YES completion:nil];
}
+- (IBAction)invalidatePacks:(id)sender {
+ for (MGLOfflinePack *pack in [MGLOfflineStorage sharedOfflineStorage].packs) {
+
+ CFTimeInterval start = CACurrentMediaTime();
+ [[MGLOfflineStorage sharedOfflineStorage] invalidatePack:pack withCompletionHandler:^(NSError * _Nullable error) {
+ CFTimeInterval end = CACurrentMediaTime();
+ CFTimeInterval difference = end - start;
+ NSLog(@"invalidatePack Started: %f Ended: %f Total Time: %f", start, end, difference);
+ }];
+ }
+}
+
+
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
diff --git a/platform/ios/app/Main.storyboard b/platform/ios/app/Main.storyboard
index f4e535a56c..28316745a1 100644
--- a/platform/ios/app/Main.storyboard
+++ b/platform/ios/app/Main.storyboard
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="PSe-Ot-7Ff">
- <device id="retina4_7" orientation="portrait">
- <adaptation id="fullscreen"/>
- </device>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14810.11" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="PSe-Ot-7Ff">
+ <device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14766.13"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -15,14 +13,14 @@
<objects>
<viewController id="WaX-pd-UZQ" userLabel="Map View Controller" customClass="MBXViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Z9X-fc-PUC">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <rect key="frame" x="0.0" y="0.0" width="203" height="33"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kNe-zV-9ha" customClass="MGLMapView">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <rect key="frame" x="0.0" y="0.0" width="203" height="33"/>
<subviews>
<button hidden="YES" opaque="NO" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="58y-pX-YyB">
- <rect key="frame" x="8" y="102" width="40" height="20"/>
+ <rect key="frame" x="8" y="82" width="40" height="20"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" button="YES" notEnabled="YES"/>
@@ -40,7 +38,7 @@
</userDefinedRuntimeAttributes>
</button>
<view hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BHE-Wn-x69" customClass="MBXFrameTimeGraphView">
- <rect key="frame" x="0.0" y="467" width="375" height="200"/>
+ <rect key="frame" x="0.0" y="-167" width="203" height="200"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" notEnabled="YES"/>
@@ -143,7 +141,7 @@
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fGu-Ys-Eh1" id="sUf-bc-8xG">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="My Inactive Offline Pack" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="JtH-Ce-MI5">
@@ -167,7 +165,7 @@
<rect key="frame" x="0.0" y="72" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="mKB-tz-Zfl" id="nS3-aU-nBr">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="My Active Offline Pack" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9ZK-gS-wJ4">
@@ -194,11 +192,18 @@
</connections>
</tableView>
<navigationItem key="navigationItem" title="Offline Packs" id="UcK-PK-eQA">
- <barButtonItem key="rightBarButtonItem" systemItem="add" id="gCV-hl-Mzc">
- <connections>
- <action selector="addCurrentRegion:" destination="7q0-lI-zqb" id="G2O-3V-aEA"/>
- </connections>
- </barButtonItem>
+ <rightBarButtonItems>
+ <barButtonItem systemItem="add" id="gCV-hl-Mzc">
+ <connections>
+ <action selector="addCurrentRegion:" destination="7q0-lI-zqb" id="G2O-3V-aEA"/>
+ </connections>
+ </barButtonItem>
+ <barButtonItem style="plain" systemItem="refresh" id="2fx-iS-Veb">
+ <connections>
+ <action selector="invalidatePacks:" destination="7q0-lI-zqb" id="5lx-FY-aTt"/>
+ </connections>
+ </barButtonItem>
+ </rightBarButtonItems>
</navigationItem>
<connections>
<segue destination="x2D-ga-sM5" kind="unwind" identifier="ReturnToMap" unwindAction="unwindToMapViewController:" id="6MZ-Ed-tu2"/>
@@ -215,7 +220,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="PSe-Ot-7Ff" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="ONr-CS-J5X">
- <rect key="frame" x="0.0" y="20" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@@ -257,7 +262,7 @@
</constraints>
</scrollView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="l5l-w7-P80" userLabel="Control Panel View">
- <rect key="frame" x="0.0" y="20" width="375" height="64"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="64"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Zoom" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DgB-BD-Ltx">
<rect key="frame" x="29.5" y="6" width="35" height="16"/>
@@ -381,22 +386,22 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="miZ-Fw-EWq" userLabel="Image View TL">
- <rect key="frame" x="0.0" y="64" width="125" height="301.5"/>
+ <rect key="frame" x="0.0" y="44" width="125" height="311.5"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="XuN-T4-Z83" userLabel="Image View TM">
- <rect key="frame" x="125" y="64" width="125" height="301.5"/>
+ <rect key="frame" x="125" y="44" width="125" height="311.5"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ykR-Ku-i9l" userLabel="Image View TR">
- <rect key="frame" x="250" y="64" width="125" height="301.5"/>
+ <rect key="frame" x="250" y="44" width="125" height="311.5"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TL0-V8-T2F" userLabel="Image View BL">
- <rect key="frame" x="0.0" y="365.5" width="125" height="301.5"/>
+ <rect key="frame" x="0.0" y="355.5" width="125" height="311.5"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="eMy-JU-rq4" userLabel="Image View BM">
- <rect key="frame" x="125" y="365.5" width="125" height="301.5"/>
+ <rect key="frame" x="125" y="355.5" width="125" height="311.5"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="zT0-3J-0xw" userLabel="Image View BR">
- <rect key="frame" x="250" y="365.5" width="125" height="301.5"/>
+ <rect key="frame" x="250" y="355.5" width="125" height="311.5"/>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 670e78a46c..98a651f13f 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -516,6 +516,7 @@
CA6914B520E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA6914B420E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m */; };
CA7766832229C10E0008DE9E /* MGLCompactCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848451CBAFB9800AB86E3 /* MGLCompactCalloutView.m */; };
CA7766842229C11A0008DE9E /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA88488A1CBB037E00AB86E3 /* SMCalloutView.m */; };
+ CA86FF0E22D8D5A0009EB14A /* MGLNetworkConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA86FF0D22D8D5A0009EB14A /* MGLNetworkConfigurationTests.m */; };
CA88DC3021C85D900059ED5A /* MGLStyleURLIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CA88DC2F21C85D900059ED5A /* MGLStyleURLIntegrationTest.m */; };
CA8FBC0921A47BB100D1203C /* MGLRendererConfigurationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA8FBC0821A47BB100D1203C /* MGLRendererConfigurationTests.mm */; };
CAA69DA4206DCD0E007279CD /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; };
@@ -1198,6 +1199,7 @@
CA5E5042209BDC5F001A8A81 /* MGLTestUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MGLTestUtility.h; path = ../../darwin/test/MGLTestUtility.h; sourceTree = "<group>"; };
CA65C4F721E9BB080068B0D4 /* MGLCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCluster.h; sourceTree = "<group>"; };
CA6914B420E67F50002DB0EE /* MGLAnnotationViewIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLAnnotationViewIntegrationTests.m; path = "Annotation Tests/MGLAnnotationViewIntegrationTests.m"; sourceTree = "<group>"; };
+ CA86FF0D22D8D5A0009EB14A /* MGLNetworkConfigurationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLNetworkConfigurationTests.m; sourceTree = "<group>"; };
CA88DC2F21C85D900059ED5A /* MGLStyleURLIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLStyleURLIntegrationTest.m; sourceTree = "<group>"; };
CA8FBC0821A47BB100D1203C /* MGLRendererConfigurationTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLRendererConfigurationTests.mm; path = ../../darwin/test/MGLRendererConfigurationTests.mm; sourceTree = "<group>"; };
CAD9D0A922A86D6F001B25EE /* MGLResourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLResourceTests.mm; path = ../../darwin/test/MGLResourceTests.mm; sourceTree = "<group>"; };
@@ -2071,6 +2073,7 @@
357579811D502AD4000B822E /* Styling */,
409F43FB1E9E77D10048729D /* Swift Integration */,
4031ACFD1E9FD26900A3EA26 /* Test Helpers */,
+ CA86FF0D22D8D5A0009EB14A /* MGLNetworkConfigurationTests.m */,
);
name = "SDK Tests";
path = test;
@@ -3250,6 +3253,7 @@
DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */,
DA35A2C61CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */,
DAE7DEC21E245455007505A6 /* MGLNSStringAdditionsTests.m in Sources */,
+ CA86FF0E22D8D5A0009EB14A /* MGLNetworkConfigurationTests.m in Sources */,
4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */,
DAEDC4341D603417000224FF /* MGLAttributionInfoTests.m in Sources */,
1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */,
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index d027f616bd..d77f94d8ba 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -297,8 +297,8 @@ public:
NSInteger _changeDelimiterSuppressionDepth;
- /// Center coordinate of the pinch gesture on the previous iteration of the gesture.
- CLLocationCoordinate2D _previousPinchCenterCoordinate;
+ /// Center of the pinch gesture on the previous iteration of the gesture.
+ CGPoint _previousPinchCenterPoint;
NSUInteger _previousPinchNumberOfTouches;
CLLocationDistance _distanceFromOldUserLocation;
@@ -1643,11 +1643,7 @@ public:
// meaningless.
if (self.userTrackingMode == MGLUserTrackingModeNone && pinch.numberOfTouches == _previousPinchNumberOfTouches)
{
- CLLocationCoordinate2D centerCoordinate = _previousPinchCenterCoordinate;
- mbgl::EdgeInsets padding { centerPoint.y, centerPoint.x, self.size.height - centerPoint.y, self.size.width - centerPoint.x };
- self.mbglMap.jumpTo(mbgl::CameraOptions()
- .withCenter(MGLLatLngFromLocationCoordinate2D(centerCoordinate))
- .withPadding(padding));
+ self.mbglMap.moveBy({centerPoint.x - _previousPinchCenterPoint.x, centerPoint.y - _previousPinchCenterPoint.y});
}
}
[self cameraIsChanging];
@@ -1705,7 +1701,7 @@ public:
[self unrotateIfNeededForGesture];
}
- _previousPinchCenterCoordinate = [self convertPoint:centerPoint toCoordinateFromView:self];
+ _previousPinchCenterPoint = centerPoint;
_previousPinchNumberOfTouches = pinch.numberOfTouches;
}
diff --git a/platform/ios/test/MGLNetworkConfigurationTests.m b/platform/ios/test/MGLNetworkConfigurationTests.m
new file mode 100644
index 0000000000..bfb63f57af
--- /dev/null
+++ b/platform/ios/test/MGLNetworkConfigurationTests.m
@@ -0,0 +1,43 @@
+#import <Mapbox/Mapbox.h>
+#import <XCTest/XCTest.h>
+#import "MGLNetworkConfiguration_Private.h"
+
+@interface MGLNetworkConfigurationTests : XCTestCase
+@end
+
+@implementation MGLNetworkConfigurationTests
+
+// Regression test for https://github.com/mapbox/mapbox-gl-native/issues/14982
+- (void)testAccessingEventsFromMultipleThreads {
+ MGLNetworkConfiguration *configuration = [[MGLNetworkConfiguration alloc] init];
+
+ // Concurrent
+ dispatch_queue_t queue = dispatch_queue_create("com.mapbox.testAccessingEventsFromMultipleThreads", DISPATCH_QUEUE_CONCURRENT);
+
+ NSUInteger numberOfConcurrentBlocks = 20;
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"wait-for-threads"];
+ expectation.expectedFulfillmentCount = numberOfConcurrentBlocks;
+
+ for (NSUInteger i = 0; i < numberOfConcurrentBlocks; i++) {
+
+ NSString *event = [NSString stringWithFormat:@"test://event-%ld", i];
+ NSString *resourceType = @"test";
+
+ dispatch_async(queue, ^{
+ [configuration startDownloadEvent:event type:resourceType];
+
+ NSURL *url = [NSURL URLWithString:event];
+ NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:nil expectedContentLength:0 textEncodingName:nil];
+
+ [configuration stopDownloadEventForResponse:response];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [expectation fulfill];
+ });
+ });
+ }
+
+ [self waitForExpectations:@[expectation] timeout:10.0];
+}
+@end
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 17ea823784..88fa37052b 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -4,11 +4,11 @@
* Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816))
* Fixed queryRenderedFeatues bug caused by incorrect sort feature index calculation. ([#14884](https://github.com/mapbox/mapbox-gl-native/pull/14884))
-* The `MGLIdeographicFontFamilyName` Info.plist key now also accepts an array of font family names, to customize font fallback behavior. It can also be set to a Boolean value of `NO` to force the SDK to typeset CJK characters in a remote font specified by `MGLSymbolStyleLayer.textFontNames`. ([#14862](https://github.com/mapbox/mapbox-gl-native/pull/14862))
+* Ideographic glyphs from Chinese, Japanese, and Korean are no longer downloaded by default as part of offline packs; they are instead rendered on-device, saving bandwidth and storage while improving performance. ([#14176](https://github.com/mapbox/mapbox-gl-native/pull/14176))
+* The `MGLIdeographicFontFamilyName` Info.plist key now also accepts an array of font family names, to customize font fallback behavior. It can also be set to a Boolean value of `NO` to force the SDK to typeset CJK characters in a remote font specified by `MGLSymbolStyleLayer.textFontNames`. ([#14862](https://github.com/mapbox/mapbox-gl-native/pull/14862))
* Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930))
* Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065))
-
### Styles and rendering
* Setting `MGLMapView.contentInset` now moves the map’s focal point to the center of the content frame after insetting. ([#14664](https://github.com/mapbox/mapbox-gl-native/pull/14664))
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index 213aa33107..1ab8b690b9 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -932,8 +932,8 @@ NSArray<id <MGLAnnotation>> *MBXFlattenedShapes(NSArray<id <MGLAnnotation>> *sha
self.minimumOfflinePackZoomLevelFormatter.maximum = @(ceil(self.mapView.maximumZoomLevel));
self.maximumOfflinePackZoomLevelFormatter.maximum = @(ceil(self.mapView.maximumZoomLevel));
- NSString *fontFamilyName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLIdeographicFontFamilyName"];
- self.includesIdeographicGlyphsBox.state = fontFamilyName ? NSOffState : NSOnState;
+ id ideographicFontFamilyName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLIdeographicFontFamilyName"];
+ self.includesIdeographicGlyphsBox.state = ([ideographicFontFamilyName isKindOfClass:[NSNumber class]] && ![ideographicFontFamilyName boolValue]) ? NSOffState : NSOnState;
[self.addOfflinePackWindow makeFirstResponder:self.offlinePackNameField];
__weak __typeof__(self) weakSelf = self;
diff --git a/platform/node/CHANGELOG.md b/platform/node/CHANGELOG.md
index e03a64b049..2999a70f05 100644
--- a/platform/node/CHANGELOG.md
+++ b/platform/node/CHANGELOG.md
@@ -1,9 +1,12 @@
-# master
+# 4.2.0
+- Add an option to set whether or not an image should be treated as a SDF ([#15054](https://github.com/mapbox/mapbox-gl-native/issues/15054))
+- Fix problems associated with node 10 and NAN [#14847](https://github.com/mapbox/mapbox-gl-native/pull/14847)
+
+# 4.1.0
- Add `symbol-z-order` symbol layout property to style spec [#12783](https://github.com/mapbox/mapbox-gl-native/pull/12783)
- Add `crossSourceCollisions` map option, with default of `true`. When set to `false`, cross-source collision detection is disabled. ([#12820] (https://github.com/mapbox/mapbox-gl-native/issues/12820))
- Fixed bugs in coercion expression operators ("to-array" applied to empty arrays, "to-color" applied to colors, and "to-number" applied to null) [#12864](https://github.com/mapbox/mapbox-gl-native/pull/12864)
- Fixed an issue where fill and line layers would occasionally flicker on zoom ([#12982](https://github.com/mapbox/mapbox-gl-native/pull/12982))
-- Add an option to set whether or not an image should be treated as a SDF ([#15054](https://github.com/mapbox/mapbox-gl-native/issues/15054))
# 4.0.0
- Many new features and enhancements, including: