diff options
Diffstat (limited to 'platform/darwin/src')
-rw-r--r-- | platform/darwin/src/MGLOfflinePack.mm | 21 | ||||
-rw-r--r-- | platform/darwin/src/MGLOfflineRegion.h | 15 | ||||
-rw-r--r-- | platform/darwin/src/MGLOfflineRegion_Private.h | 9 | ||||
-rw-r--r-- | platform/darwin/src/MGLOfflineStorage.mm | 2 | ||||
-rw-r--r-- | platform/darwin/src/MGLShapeOfflineRegion.h | 72 | ||||
-rw-r--r-- | platform/darwin/src/MGLShapeOfflineRegion.mm | 120 | ||||
-rw-r--r-- | platform/darwin/src/MGLShapeOfflineRegion_Private.h | 22 | ||||
-rw-r--r-- | platform/darwin/src/MGLTilePyramidOfflineRegion.h | 14 | ||||
-rw-r--r-- | platform/darwin/src/MGLTilePyramidOfflineRegion.mm | 5 | ||||
-rw-r--r-- | platform/darwin/src/MGLTilePyramidOfflineRegion_Private.h | 22 |
10 files changed, 275 insertions, 27 deletions
diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index 7bbc681c88..bafb976585 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -3,6 +3,9 @@ #import "MGLOfflineStorage_Private.h" #import "MGLOfflineRegion_Private.h" #import "MGLTilePyramidOfflineRegion.h" +#import "MGLTilePyramidOfflineRegion_Private.h" +#import "MGLShapeOfflineRegion.h" +#import "MGLShapeOfflineRegion_Private.h" #import "NSValue+MGLAdditions.h" @@ -27,6 +30,12 @@ const MGLExceptionName MGLInvalidOfflinePackException = @"MGLInvalidOfflinePackE } \ } while (NO); +@interface MGLTilePyramidOfflineRegion () <MGLOfflineRegion_Private, MGLTilePyramidOfflineRegion_Private> +@end + +@interface MGLShapeOfflineRegion () <MGLOfflineRegion_Private, MGLShapeOfflineRegion_Private> +@end + class MBGLOfflineRegionObserver : public mbgl::OfflineRegionObserver { public: MBGLOfflineRegionObserver(MGLOfflinePack *pack_) : pack(pack_) {} @@ -78,7 +87,17 @@ private: const mbgl::OfflineRegionDefinition ®ionDefinition = _mbglOfflineRegion->getDefinition(); NSAssert([MGLTilePyramidOfflineRegion conformsToProtocol:@protocol(MGLOfflineRegion_Private)], @"MGLTilePyramidOfflineRegion should conform to MGLOfflineRegion_Private."); - return [(id <MGLOfflineRegion_Private>)[MGLTilePyramidOfflineRegion alloc] initWithOfflineRegionDefinition:regionDefinition]; + NSAssert([MGLShapeOfflineRegion conformsToProtocol:@protocol(MGLOfflineRegion_Private)], @"MGLShapeOfflineRegion should conform to MGLOfflineRegion_Private."); + + + + return regionDefinition.match( + [&] (const mbgl::OfflineTilePyramidRegionDefinition def){ + return (id <MGLOfflineRegion>)[[MGLTilePyramidOfflineRegion alloc] initWithOfflineRegionDefinition:def]; + }, + [&] (const mbgl::OfflineGeometryRegionDefinition& def){ + return (id <MGLOfflineRegion>)[[MGLShapeOfflineRegion alloc] initWithOfflineRegionDefinition:def]; + }); } - (NSData *)context { diff --git a/platform/darwin/src/MGLOfflineRegion.h b/platform/darwin/src/MGLOfflineRegion.h index fe0ab6cb7f..3e0f485e2c 100644 --- a/platform/darwin/src/MGLOfflineRegion.h +++ b/platform/darwin/src/MGLOfflineRegion.h @@ -4,12 +4,21 @@ NS_ASSUME_NONNULL_BEGIN /** An object conforming to the `MGLOfflineRegion` protocol determines which - resources are required by an `MGLOfflinePack` object. At present, only - instances of `MGLTilePyramidOfflineRegion` may be used as `MGLOfflinePack` - regions, but additional conforming implementations may be added in the future. + resources are required by an `MGLOfflinePack` object. */ @protocol MGLOfflineRegion <NSObject> +/** + 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}`). + */ +@property (nonatomic, readonly) NSURL *styleURL; + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLOfflineRegion_Private.h b/platform/darwin/src/MGLOfflineRegion_Private.h index b1dec8dd64..c1f3fd5200 100644 --- a/platform/darwin/src/MGLOfflineRegion_Private.h +++ b/platform/darwin/src/MGLOfflineRegion_Private.h @@ -9,15 +9,6 @@ NS_ASSUME_NONNULL_BEGIN @protocol MGLOfflineRegion_Private <MGLOfflineRegion> /** - 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. - */ -- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition; - -/** Creates and returns a C++ offline region definition corresponding to the receiver. */ diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 05e1b06338..93a6da36c4 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -285,7 +285,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio return; } - const mbgl::OfflineTilePyramidRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition]; + const mbgl::OfflineRegionDefinition regionDefinition = [(id <MGLOfflineRegion_Private>)region offlineRegionDefinition]; mbgl::OfflineRegionMetadata metadata(context.length); [context getBytes:&metadata[0] length:metadata.size()]; self.mbglFileSource->createOfflineRegion(regionDefinition, metadata, [&, completion](mbgl::expected<mbgl::OfflineRegion, std::exception_ptr> mbglOfflineRegion) { diff --git a/platform/darwin/src/MGLShapeOfflineRegion.h b/platform/darwin/src/MGLShapeOfflineRegion.h new file mode 100644 index 0000000000..ac54dc137b --- /dev/null +++ b/platform/darwin/src/MGLShapeOfflineRegion.h @@ -0,0 +1,72 @@ +#import <Foundation/Foundation.h> + +#import "MGLFoundation.h" +#import "MGLOfflineRegion.h" +#import "MGLShape.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + An offline region defined by a style URL, geographic shape, and + range of zoom levels. + + This class requires fewer resources than MGLTilePyramidOfflineRegion + for irregularly shaped regions. + */ +MGL_EXPORT +@interface MGLShapeOfflineRegion : NSObject <MGLOfflineRegion, NSSecureCoding, NSCopying> + +/** + The shape for the geographic region covered by the downloaded + tiles. + */ +@property (nonatomic, readonly) MGLShape *shape; + +/** + 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; + +- (instancetype)init NS_UNAVAILABLE; + +/** + Initializes a newly created offline region with the given style URL, geometry, + and range of zoom levels. + + This is the designated initializer for `MGLShapeOfflineRegion`. + + @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. + Relative file URLs cannot be used as offline style URLs. To download the + online resources required by a local style, specify a URL to an online copy + of the style. + @param shape The shape of the geographic region to be covered by + the downloaded tiles. + @param minimumZoomLevel The minimum zoom level to be covered by the downloaded + tiles. This parameter should be set to at least 0 but no greater than the + value of the `maximumZoomLevel` parameter. For each required tile source, if + this parameter is set to a value less than the tile source’s minimum zoom + level, the download covers zoom levels down to the tile source’s minimum + zoom level. + @param maximumZoomLevel The maximum zoom level to be covered by the downloaded + tiles. This parameter should be set to at least the value of the + `minimumZoomLevel` parameter. For each required tile source, if this + parameter is set to a value greater than the tile source’s minimum zoom + level, the download covers zoom levels up to the tile source’s maximum zoom + level. + */ +- (instancetype)initWithStyleURL:(nullable NSURL *)styleURL shape:(MGLShape *)shape fromZoomLevel:(double)minimumZoomLevel toZoomLevel:(double)maximumZoomLevel NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLShapeOfflineRegion.mm b/platform/darwin/src/MGLShapeOfflineRegion.mm new file mode 100644 index 0000000000..e1393f1199 --- /dev/null +++ b/platform/darwin/src/MGLShapeOfflineRegion.mm @@ -0,0 +1,120 @@ +#import "MGLShapeOfflineRegion.h" + +#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR + #import <Cocoa/Cocoa.h> +#else + #import <UIKit/UIKit.h> +#endif + +#import "MGLOfflineRegion_Private.h" +#import "MGLShapeOfflineRegion_Private.h" +#import "MGLFeature_Private.h" +#import "MGLShape_Private.h" +#import "MGLStyle.h" + +@interface MGLShapeOfflineRegion () <MGLOfflineRegion_Private, MGLShapeOfflineRegion_Private> + +@end + +@implementation MGLShapeOfflineRegion { + NSURL *_styleURL; +} + +@synthesize styleURL = _styleURL; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)init { + [NSException raise:@"Method unavailable" + format: + @"-[MGLShapeOfflineRegion init] is unavailable. " + @"Use -initWithStyleURL:shape:fromZoomLevel:toZoomLevel: instead."]; + return nil; +} + +- (instancetype)initWithStyleURL:(NSURL *)styleURL shape:(MGLShape *)shape fromZoomLevel:(double)minimumZoomLevel toZoomLevel:(double)maximumZoomLevel { + if (self = [super init]) { + 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. " + @"To download the online resources required by this style, " + @"specify a URL to an online copy of this style. " + @"For Mapbox-hosted styles, use the mapbox: scheme.", + NSStringFromClass([self class])]; + } + + _styleURL = styleURL; + _shape = shape; + _minimumZoomLevel = minimumZoomLevel; + _maximumZoomLevel = maximumZoomLevel; + } + return self; +} + +- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineGeometryRegionDefinition &)definition { + NSURL *styleURL = [NSURL URLWithString:@(definition.styleURL.c_str())]; + MGLShape *shape = MGLShapeFromGeoJSON(definition.geometry); + return [self initWithStyleURL:styleURL shape:shape fromZoomLevel:definition.minZoom toZoomLevel:definition.maxZoom]; +} + +- (const mbgl::OfflineRegionDefinition)offlineRegionDefinition { +#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR + const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; +#elif TARGET_OS_MAC + const float scaleFactor = [NSScreen mainScreen].backingScaleFactor; +#endif + return mbgl::OfflineGeometryRegionDefinition(_styleURL.absoluteString.UTF8String, + _shape.geometryObject, + _minimumZoomLevel, _maximumZoomLevel, + scaleFactor); +} + +- (nullable instancetype)initWithCoder:(NSCoder *)coder { + NSURL *styleURL = [coder decodeObjectForKey:@"styleURL"]; + MGLShape * shape = [coder decodeObjectForKey:@"shape"]; + double minimumZoomLevel = [coder decodeDoubleForKey:@"minimumZoomLevel"]; + double maximumZoomLevel = [coder decodeDoubleForKey:@"maximumZoomLevel"]; + + return [self initWithStyleURL:styleURL shape:shape fromZoomLevel:minimumZoomLevel toZoomLevel:maximumZoomLevel]; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [coder encodeObject:_styleURL forKey:@"styleURL"]; + [coder encodeObject:_shape forKey:@"shape"]; + [coder encodeDouble:_maximumZoomLevel forKey:@"maximumZoomLevel"]; + [coder encodeDouble:_minimumZoomLevel forKey:@"minimumZoomLevel"]; +} + +- (id)copyWithZone:(nullable NSZone *)zone { + return [[[self class] allocWithZone:zone] initWithStyleURL:_styleURL shape:_shape fromZoomLevel:_minimumZoomLevel toZoomLevel:_maximumZoomLevel]; +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (![other isKindOfClass:[self class]]) { + return NO; + } + + MGLShapeOfflineRegion *otherRegion = other; + return (_minimumZoomLevel == otherRegion->_minimumZoomLevel + && _maximumZoomLevel == otherRegion->_maximumZoomLevel + && _shape.geometryObject == otherRegion->_shape.geometryObject + && [_styleURL isEqual:otherRegion->_styleURL]); +} + +- (NSUInteger)hash { + return (_styleURL.hash + + _shape.hash + + @(_minimumZoomLevel).hash + @(_maximumZoomLevel).hash); +} + +@end diff --git a/platform/darwin/src/MGLShapeOfflineRegion_Private.h b/platform/darwin/src/MGLShapeOfflineRegion_Private.h new file mode 100644 index 0000000000..2ab44ad405 --- /dev/null +++ b/platform/darwin/src/MGLShapeOfflineRegion_Private.h @@ -0,0 +1,22 @@ +#import <Foundation/Foundation.h> + +#import "MGLOfflineRegion.h" + +#include <mbgl/storage/offline.hpp> + +NS_ASSUME_NONNULL_BEGIN + +@protocol MGLShapeOfflineRegion_Private <MGLOfflineRegion> + +/** + 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. + */ +- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineGeometryRegionDefinition &)definition; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.h b/platform/darwin/src/MGLTilePyramidOfflineRegion.h index 31e5a41920..4fbb68dbc6 100644 --- a/platform/darwin/src/MGLTilePyramidOfflineRegion.h +++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.h @@ -9,22 +9,14 @@ NS_ASSUME_NONNULL_BEGIN /** An offline region defined by a style URL, geographic coordinate bounds, and range of zoom levels. + + To minimize the resources required by an irregularly shaped offline region, + use the MGLShapeOfflineRegion class instead. */ 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}`). - */ -@property (nonatomic, readonly) NSURL *styleURL; - -/** The coordinate bounds for the geographic region covered by the downloaded tiles. */ diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm index 7333703267..0766d224da 100644 --- a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm +++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm @@ -5,10 +5,11 @@ #endif #import "MGLOfflineRegion_Private.h" +#import "MGLTilePyramidOfflineRegion_Private.h" #import "MGLGeometry_Private.h" #import "MGLStyle.h" -@interface MGLTilePyramidOfflineRegion () <MGLOfflineRegion_Private> +@interface MGLTilePyramidOfflineRegion () <MGLOfflineRegion_Private, MGLTilePyramidOfflineRegion_Private> @end @@ -52,7 +53,7 @@ return self; } -- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition { +- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineTilePyramidRegionDefinition &)definition { NSURL *styleURL = [NSURL URLWithString:@(definition.styleURL.c_str())]; MGLCoordinateBounds bounds = MGLCoordinateBoundsFromLatLngBounds(definition.bounds); return [self initWithStyleURL:styleURL bounds:bounds fromZoomLevel:definition.minZoom toZoomLevel:definition.maxZoom]; diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion_Private.h b/platform/darwin/src/MGLTilePyramidOfflineRegion_Private.h new file mode 100644 index 0000000000..90d8e05477 --- /dev/null +++ b/platform/darwin/src/MGLTilePyramidOfflineRegion_Private.h @@ -0,0 +1,22 @@ +#import <Foundation/Foundation.h> + +#import "MGLOfflineRegion.h" + +#include <mbgl/storage/offline.hpp> + +NS_ASSUME_NONNULL_BEGIN + +@protocol MGLTilePyramidOfflineRegion_Private <MGLOfflineRegion> + +/** + 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. + */ +- (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineTilePyramidRegionDefinition &)definition; + +@end + +NS_ASSUME_NONNULL_END |