diff options
author | Fabian Guerra Soto <fabian.guerra@mapbox.com> | 2017-10-04 10:03:03 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-04 10:03:03 -0400 |
commit | f01588cac78b5e5411385faa451080a74320500b (patch) | |
tree | 1f0540cf5c71475f0ae6714d70b909338fed9b5f /platform/darwin/src/MGLMapSnapshotter.mm | |
parent | 6a846ce5a8ff1d62f4eafa3ef5bd0427096ca9e6 (diff) | |
download | qtlocation-mapboxgl-f01588cac78b5e5411385faa451080a74320500b.tar.gz |
[ios, macos] Improve snap shotter documentation. (#10020)
* [ios, macos] Improve snap shotter documentation.
* [macos] Save snapshots in correct format
* [macos] Renamed snapshot item to Export Image
* [ios, macos] Clarify Snapshotter documentation.
* [ios] Fix snapshot scale
* [macOS] Fix snapshotter 4x scaling.
* [ios] Fix snapshotter final image scale.
* [ios, macos] Update snapshotter size documentation.
* [ios, macos] Throw an exception when the snapshotter has already started.
* [ios, macos] Add snapshotter header example.
* [ios, macos] Use one of the predefined Foundation's exception names.
Diffstat (limited to 'platform/darwin/src/MGLMapSnapshotter.mm')
-rw-r--r-- | platform/darwin/src/MGLMapSnapshotter.mm | 78 |
1 files changed, 51 insertions, 27 deletions
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm index c81fd39c4a..12b932daa3 100644 --- a/platform/darwin/src/MGLMapSnapshotter.mm +++ b/platform/darwin/src/MGLMapSnapshotter.mm @@ -13,6 +13,7 @@ #import "MGLOfflineStorage_Private.h" #import "MGLGeometry_Private.h" #import "NSBundle+MGLAdditions.h" +#import "MGLStyle.h" #if TARGET_OS_IPHONE #import "UIImage+MGLAdditions.h" @@ -20,12 +21,19 @@ #import "NSImage+MGLAdditions.h" #endif +const CGPoint MGLLogoImagePosition = CGPointMake(8, 8); +const CGFloat MGLSnapshotterMinimumPixelSize = 64; + @implementation MGLMapSnapshotOptions -- (instancetype _Nonnull)initWithStyleURL:(NSURL* _Nonnull)styleURL camera:(MGLMapCamera*)camera size:(CGSize) size; +- (instancetype _Nonnull)initWithStyleURL:(nullable NSURL*)styleURL camera:(MGLMapCamera*)camera size:(CGSize) size; { self = [super init]; if (self) { + if ( !styleURL) + { + styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion]; + } _styleURL = styleURL; _size = size; _camera = camera; @@ -41,28 +49,34 @@ @end +@interface MGLMapSnapshotter() +@property (nonatomic) MGLMapSnapshotOptions *options; +@end + @implementation MGLMapSnapshotter { - std::shared_ptr<mbgl::ThreadPool> mbglThreadPool; - std::unique_ptr<mbgl::MapSnapshotter> mbglMapSnapshotter; - std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> snapshotCallback; + std::shared_ptr<mbgl::ThreadPool> _mbglThreadPool; + std::unique_ptr<mbgl::MapSnapshotter> _mbglMapSnapshotter; + std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> _snapshotCallback; } - (instancetype)initWithOptions:(MGLMapSnapshotOptions*)options; { self = [super init]; if (self) { + _options = options; _loading = false; mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource; - mbglThreadPool = mbgl::sharedThreadPool(); + _mbglThreadPool = mbgl::sharedThreadPool(); std::string styleURL = std::string([options.styleURL.absoluteString UTF8String]); // Size; taking into account the minimum texture size for OpenGL ES + // For non retina screens the ratio is 1:1 MGLSnapshotterMinimumPixelSize mbgl::Size size = { - static_cast<uint32_t>(MAX(options.size.width, 64)), - static_cast<uint32_t>(MAX(options.size.height, 64)) + static_cast<uint32_t>(MAX(options.size.width, MGLSnapshotterMinimumPixelSize)), + static_cast<uint32_t>(MAX(options.size.height, MGLSnapshotterMinimumPixelSize)) }; float pixelRatio = MAX(options.scale, 1); @@ -73,17 +87,17 @@ cameraOptions.center = MGLLatLngFromLocationCoordinate2D(options.camera.centerCoordinate); } cameraOptions.angle = MAX(0, options.camera.heading) * mbgl::util::DEG2RAD; - cameraOptions.zoom = MAX(0, options.zoom); + cameraOptions.zoom = MAX(0, options.zoomLevel); cameraOptions.pitch = MAX(0, options.camera.pitch); // Region - mbgl::optional<mbgl::LatLngBounds> region; - if (!MGLCoordinateBoundsIsEmpty(options.region)) { - region = MGLLatLngBoundsFromCoordinateBounds(options.region); + mbgl::optional<mbgl::LatLngBounds> coordinateBounds; + if (!MGLCoordinateBoundsIsEmpty(options.coordinateBounds)) { + coordinateBounds = MGLLatLngBoundsFromCoordinateBounds(options.coordinateBounds); } // Create the snapshotter - mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(*mbglFileSource, *mbglThreadPool, styleURL, size, pixelRatio, cameraOptions, region); + _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(*mbglFileSource, *_mbglThreadPool, styleURL, size, pixelRatio, cameraOptions, coordinateBounds); } return self; } @@ -96,30 +110,30 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion; { if ([self isLoading]) { - NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Already started this snapshotter"}; - NSError *error = [NSError errorWithDomain:MGLErrorDomain code:1 userInfo:userInfo]; - dispatch_async(queue, ^{ - completion(nil, error); - }); - return; + [NSException raise:NSInternalInconsistencyException + format:@"Already started this snapshotter."]; } _loading = true; dispatch_async(queue, ^{ - snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image) { + _snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image) { _loading = false; if (mbglError) { NSString *description = @(mbgl::util::toString(mbglError).c_str()); NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description}; - NSError *error = [NSError errorWithDomain:MGLErrorDomain code:1 userInfo:userInfo]; + NSError *error = [NSError errorWithDomain:MGLErrorDomain code:MGLErrorCodeSnapshotFailed userInfo:userInfo]; // Dispatch result to origin queue dispatch_async(queue, ^{ completion(nil, error); }); } else { +#if TARGET_OS_IPHONE + MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image) scale:self.options.scale]; +#else MGLImage *mglImage = [[MGLImage alloc] initWithMGLPremultipliedImage:std::move(image)]; +#endif // Process image watermark in a work queue dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); @@ -127,20 +141,30 @@ #if TARGET_OS_IPHONE UIImage *logoImage = [UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil]; - UIGraphicsBeginImageContext(mglImage.size); + UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale); [mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)]; - [logoImage drawInRect:CGRectMake(8, mglImage.size.height - (8 + logoImage.size.height), logoImage.size.width,logoImage.size.height)]; + [logoImage drawInRect:CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width,logoImage.size.height)]; UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); #else NSImage *logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox" ofType:@"pdf"]]; - NSImage *compositedImage = mglImage; + NSImage *sourceImage = mglImage; + + NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height); + NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height); + NSImage *compositedImage = nil; + NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame + context:nil + hints:nil]; + compositedImage = [[NSImage alloc] initWithSize:targetSize]; [compositedImage lockFocus]; - [logoImage drawInRect:CGRectMake(8, 8, logoImage.size.width,logoImage.size.height)]; + [sourceImageRep drawInRect: targetFrame]; + [logoImage drawInRect:CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width,logoImage.size.height)]; [compositedImage unlockFocus]; + #endif // Dispatch result to origin queue @@ -150,14 +174,14 @@ }); } }); - mbglMapSnapshotter->snapshot(snapshotCallback->self()); + _mbglMapSnapshotter->snapshot(_snapshotCallback->self()); }); } - (void)cancel; { - snapshotCallback.reset(); - mbglMapSnapshotter.reset(); + _snapshotCallback.reset(); + _mbglMapSnapshotter.reset(); } @end |