diff options
author | Nadia Barbosa <nadiabarbosa@me.com> | 2019-09-09 16:17:58 -0700 |
---|---|---|
committer | Nadia Barbosa <nadiabarbosa@me.com> | 2019-09-13 12:11:23 -0700 |
commit | 3be0f9bc269804781a44bfcf294e22878bef9cb4 (patch) | |
tree | 2bd656312d2e2bcd1b16ca4072c136cf09474c14 | |
parent | 69bc5244eaaecb708e8a492f7017a451245d92bb (diff) | |
download | qtlocation-mapboxgl-3be0f9bc269804781a44bfcf294e22878bef9cb4.tar.gz |
[ios, macos] Introduce custom drawing overlays for MGLMapSnapshotterupstream/nb-snapshot-overlay-with-example
-rw-r--r-- | platform/darwin/src/MGLMapSnapshotter.h | 33 | ||||
-rw-r--r-- | platform/darwin/src/MGLMapSnapshotter.mm | 79 | ||||
-rw-r--r-- | platform/ios/CHANGELOG.md | 3 | ||||
-rw-r--r-- | platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m | 57 | ||||
-rw-r--r-- | platform/ios/MBXContextSnapshotViewController.m | 77 | ||||
-rw-r--r-- | platform/ios/app/MBXContextSnapshotViewController.h | 17 | ||||
-rw-r--r-- | platform/ios/app/MBXContextSnapshotViewController.m | 92 | ||||
-rw-r--r-- | platform/ios/app/Main.storyboard | 25 | ||||
-rw-r--r-- | platform/ios/ios.xcodeproj/project.pbxproj | 6 | ||||
-rw-r--r-- | platform/macos/CHANGELOG.md | 1 |
10 files changed, 374 insertions, 16 deletions
diff --git a/platform/darwin/src/MGLMapSnapshotter.h b/platform/darwin/src/MGLMapSnapshotter.h index 1ee9bd99bb..79767a8110 100644 --- a/platform/darwin/src/MGLMapSnapshotter.h +++ b/platform/darwin/src/MGLMapSnapshotter.h @@ -5,6 +5,27 @@ NS_ASSUME_NONNULL_BEGIN +MGL_EXPORT + +/** + An overlay that is placed within a `MGLMapSnapshot`. + + To access this object, use `-[MGLMapSnapshotter startWithOverlayHandler:completionHandler:]`. + */ + +@interface MGLMapSnapshotOverlay : NSObject + +/** + The current `CGContext` that snapshot is drawing within. You may use this context + to perform additional custom drawing. + */ +@property CGContextRef context; + +@end + + +typedef void (^MGLMapSnapshotOverlayHandler)(MGLMapSnapshotOverlay * _Nullable snapshotOverlay); + /** The options to use when creating images with the `MGLMapSnapshotter`. */ @@ -200,6 +221,18 @@ MGL_EXPORT */ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completionHandler; + +/* + Starts the snapshot creation and executes the specified blocks with the result + on the specified queue. Use this option if you want to add custom drawing on top of the + resulting `MGLMapSnapShot`. + + @param queue The queue to handle the result on. + @param overlayHandler The block to handle manipulation of the `MGLMapSnapshotter`'s `CGContext`. + @param completionHandler The block to handle the result in. + */ +- (void)startWithOverlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler completionHandler:(MGLMapSnapshotCompletionHandler)completionHandler; + /** Cancels the snapshot creation request, if any. diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm index 0001ebcb86..cd0ede0a97 100644 --- a/platform/darwin/src/MGLMapSnapshotter.mm +++ b/platform/darwin/src/MGLMapSnapshotter.mm @@ -32,6 +32,26 @@ const CGPoint MGLLogoImagePosition = CGPointMake(8, 8); const CGFloat MGLSnapshotterMinimumPixelSize = 64; + +@interface MGLMapSnapshotOverlay() + +- (instancetype)initWithContext:(CGContextRef)context; + +@end + +@implementation MGLMapSnapshotOverlay + +- (instancetype) initWithContext:(CGContextRef)context { + self = [super init]; + if (self) { + _context = context; + } + + return self; +} + +@end + @implementation MGLMapSnapshotOptions - (instancetype _Nonnull)initWithStyleURL:(nullable NSURL *)styleURL camera:(MGLMapCamera *)camera size:(CGSize)size @@ -183,7 +203,15 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; [self startWithQueue:dispatch_get_main_queue() completionHandler:completion]; } -- (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion +- (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completionHandler { + [self startWithQueue:queue overlayHandler:nil completionHandler:completionHandler]; +} + +- (void)startWithOverlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler completionHandler:(MGLMapSnapshotCompletionHandler)completion { + [self startWithQueue:dispatch_get_main_queue() overlayHandler:overlayHandler completionHandler:completion]; +} + +- (void)startWithQueue:(dispatch_queue_t)queue overlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler completionHandler:(MGLMapSnapshotCompletionHandler)completion { if (!mbgl::Scheduler::GetCurrent()) { [NSException raise:NSInvalidArgumentException @@ -206,6 +234,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; self.cancelled = NO; __weak __typeof__(self) weakSelf = self; + // mbgl::Scheduler::GetCurrent() scheduler means "run callback on current (ie UI/main) thread" // capture weakSelf to avoid retain cycle if callback is never called (ie snapshot cancelled) @@ -238,7 +267,8 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; mglImage.size = NSMakeSize(mglImage.size.width / strongSelf.options.scale, mglImage.size.height / strongSelf.options.scale); #endif - [strongSelf drawAttributedSnapshot:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn]; + + [strongSelf drawAttributedSnapshot:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn overlayHandler:overlayHandler]; } strongSelf->_snapshotCallback = NULL; @@ -250,7 +280,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; _mbglMapSnapshotter->snapshot(_snapshotCallback->self()); } -+ (MGLImage*)drawAttributedSnapshotWorker:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn scale:(CGFloat)scale size:(CGSize)size { ++ (MGLImage*)drawAttributedSnapshotWorker:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn scale:(CGFloat)scale size:(CGSize)size overlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler { NSArray<MGLAttributionInfo *>* attributionInfo = [MGLMapSnapshotter generateAttributionInfos:attributions]; @@ -292,6 +322,22 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, scale); [mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)]; + + CGContextRef currentContext = UIGraphicsGetCurrentContext(); + + if (currentContext && overlayHandler) { + MGLMapSnapshotOverlay *snapshotOverlay = [[MGLMapSnapshotOverlay alloc] initWithContext:currentContext]; + CGContextSaveGState(snapshotOverlay.context); + overlayHandler(snapshotOverlay); + CGContextRestoreGState(snapshotOverlay.context); + currentContext = UIGraphicsGetCurrentContext(); + } + + if (!currentContext && overlayHandler) { + // If the current context has been corrupted by the user, + // return nil so we can generate an error later. + return nil; + } [logoImage drawInRect:logoImageRect]; @@ -379,7 +425,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; #endif } -- (void)drawAttributedSnapshot:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn { +- (void)drawAttributedSnapshot:(mbgl::MapSnapshotter::Attributions)attributions snapshotImage:(MGLImage *)mglImage pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn latLngForFn:(mbgl::MapSnapshotter::LatLngForFn)latLngForFn overlayHandler:(MGLMapSnapshotOverlayHandler)overlayHandler { // Process image watermark in a work queue dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); @@ -394,19 +440,30 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; dispatch_async(workQueue, ^{ // Call a class method to ensure we're not accidentally capturing self - MGLImage *compositedImage = [MGLMapSnapshotter drawAttributedSnapshotWorker:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn scale:scale size:size]; + MGLImage *compositedImage = [MGLMapSnapshotter drawAttributedSnapshotWorker:attributions snapshotImage:mglImage pointForFn:pointForFn latLngForFn:latLngForFn scale:scale size:size overlayHandler:overlayHandler]; // Dispatch result to origin queue dispatch_async(resultQueue, ^{ __typeof__(self) strongself = weakself; if (strongself.completion) { - MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage - scale:scale - pointForFn:pointForFn - latLngForFn:latLngForFn]; - strongself.completion(snapshot, nil); - strongself.completion = nil; + + if (!compositedImage) { + NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Failed to generate composited snapshot."}; + NSError *error = [NSError errorWithDomain:MGLErrorDomain + code:MGLErrorCodeSnapshotFailed + userInfo:userInfo]; + + strongself.completion(nil, error); + strongself.completion = nil; + } else { + MGLMapSnapshot* snapshot = [[MGLMapSnapshot alloc] initWithImage:compositedImage + scale:scale + pointForFn:pointForFn + latLngForFn:latLngForFn]; + strongself.completion(snapshot, nil); + strongself.completion = nil; + } } }); }); diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 15f5904b5d..9c8ae88e79 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,9 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## master +* Added an `-[MGLMapSnapshotter startWithOverlayHandler:completionHandler:]` method to provide the snapshot's current `CGContext` in order to perform custom drawing on `MGLMapSnapShot` objects. ([#15530](https://github.com/mapbox/mapbox-gl-native/pull/15530)) + ## 5.4.0 ### Styles and rendering diff --git a/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m b/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m index 32e5fc782d..29014035a8 100644 --- a/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m +++ b/platform/ios/Integration Tests/Snapshotter Tests/MGLMapSnapshotterTest.m @@ -429,5 +429,62 @@ MGLMapSnapshotter* snapshotterWithCoordinates(CLLocationCoordinate2D coordinates [self waitForExpectations:@[expectation] timeout:10.0]; } +- (void)testSnapshotWithOverlayHandlerFailure { + if (![self validAccessToken]) { + return; + } + + CGSize size = self.mapView.bounds.size; + + XCTestExpectation *expectation = [self expectationWithDescription:@"snapshot with overlay fails"]; + expectation.expectedFulfillmentCount = 2; + + CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(30.0, 30.0); + + MGLMapSnapshotter *snapshotter = snapshotterWithCoordinates(coord, size); + XCTAssertNotNil(snapshotter); + + [snapshotter startWithOverlayHandler:^(MGLMapSnapshotOverlay * _Nullable snapshotOverlay) { + UIGraphicsEndImageContext(); + [expectation fulfill]; + } completionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) { + XCTAssertNil(snapshot); + XCTAssertNotNil(error); + [expectation fulfill]; + }]; + + [self waitForExpectations:@[expectation] timeout:10.0]; +} + +- (void)testSnapshotWithOverlayHandlerSuccess { + if (![self validAccessToken]) { + return; + } + + CGSize size = self.mapView.bounds.size; + CGRect snapshotRect = CGRectMake(0, 0, size.width, size.height); + + XCTestExpectation *expectation = [self expectationWithDescription:@"snapshot with overlay succeeds"]; + expectation.expectedFulfillmentCount = 2; + + CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(30.0, 30.0); + + MGLMapSnapshotter *snapshotter = snapshotterWithCoordinates(coord, size); + XCTAssertNotNil(snapshotter); + + [snapshotter startWithOverlayHandler:^(MGLMapSnapshotOverlay * _Nullable snapshotOverlay) { + CGContextSetFillColorWithColor(snapshotOverlay.context, [UIColor.greenColor CGColor]); + CGContextSetAlpha(snapshotOverlay.context, 0.2); + CGContextAddRect(snapshotOverlay.context, snapshotRect); + CGContextFillRect(snapshotOverlay.context, snapshotRect); + [expectation fulfill]; + } completionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) { + XCTAssertNil(error); + XCTAssertNotNil(snapshot); + [expectation fulfill]; + }]; + + [self waitForExpectations:@[expectation] timeout:10.0]; +} @end diff --git a/platform/ios/MBXContextSnapshotViewController.m b/platform/ios/MBXContextSnapshotViewController.m new file mode 100644 index 0000000000..61504f94a5 --- /dev/null +++ b/platform/ios/MBXContextSnapshotViewController.m @@ -0,0 +1,77 @@ +#import "MBXContextSnapshotViewController.h" +#import <Mapbox/Mapbox.h> + +@interface MBXContextSnapshotViewController () <MGLMapViewDelegate> +@property MGLMapView *mapView; +@property UIButton *button; +@property UIImageView *imageView; +@end + +@implementation MBXContextSnapshotViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + _mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height / 2) styleURL:[MGLStyle lightStyleURL]]; + _mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + + [_mapView setCenterCoordinate:_mapView.centerCoordinate zoomLevel:1 animated:NO]; + [self.view addSubview:_mapView]; + + + _button = [[UIButton alloc] initWithFrame:CGRectMake(_mapView.frame.origin.x + 100, _mapView.frame.origin.y + 45, 170, 30)]; + _button.layer.cornerRadius = 15; + _button.backgroundColor = [UIColor blueColor]; + [_button setTitle:@"Create snapshot" forState:UIControlStateNormal]; + [_button addTarget:self action:@selector(createSnapshot) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_button]; + + _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height / 2, self.view.bounds.size.width, self.view.bounds.size.height / 2)]; + _imageView.backgroundColor = [UIColor blackColor]; + _imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_imageView]; +} + +- (void)createSnapshot { + + MGLMapSnapshotOptions *options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:_mapView.styleURL camera:_mapView.camera size:_mapView.bounds.size]; + + options.zoomLevel = _mapView.zoomLevel; + + UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(_imageView.center.x - 30, _imageView.center.y - 30, 60, 60)]; + [self.view addSubview:indicator]; + [indicator startAnimating]; + + __block MGLMapSnapshotter *snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options]; + +// [snapshotter startWithCompletionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) { +// if (error != nil) { +// NSLog(@"Unable to create a map snapshot."); +// } else if (snapshot != nil) { +// // Add the map snapshot's image to the image view. +// [indicator stopAnimating]; +// self.imageView.image = snapshot.image; +// } +// +// snapshotter = nil; +// }]; + + [snapshotter startWithOverlayHandler:^(NSString * _Nullable testString) { + NSLog(@"STRING: %@", testString); + } completionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) { + if (error != nil) { + NSLog(@"Unable to create a map snapshot."); + } else if (snapshot != nil) { + // Add the map snapshot's image to the image view. + [indicator stopAnimating]; + self.imageView.image = snapshot.image; + } + + snapshotter = nil; + }]; + + +} + +@end diff --git a/platform/ios/app/MBXContextSnapshotViewController.h b/platform/ios/app/MBXContextSnapshotViewController.h new file mode 100644 index 0000000000..69793e5c7e --- /dev/null +++ b/platform/ios/app/MBXContextSnapshotViewController.h @@ -0,0 +1,17 @@ +// +// MBXContextSnapshotViewController.h +// iosapp +// +// Created by Nadia Barbosa on 9/9/19. +// Copyright © 2019 Mapbox. All rights reserved. +// + +#import <UIKit/UIKit.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface MBXContextSnapshotViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/ios/app/MBXContextSnapshotViewController.m b/platform/ios/app/MBXContextSnapshotViewController.m new file mode 100644 index 0000000000..09640ca95b --- /dev/null +++ b/platform/ios/app/MBXContextSnapshotViewController.m @@ -0,0 +1,92 @@ +#import "MBXContextSnapshotViewController.h" +#import <Mapbox/Mapbox.h> + +@interface MBXContextSnapshotViewController () <MGLMapViewDelegate> +@property MGLMapView *mapView; +@property UIButton *button; +@property UIImageView *imageView; +@end + +@implementation MBXContextSnapshotViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + _mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height / 2) styleURL:[MGLStyle lightStyleURL]]; + _mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + + [_mapView setCenterCoordinate:_mapView.centerCoordinate zoomLevel:1 animated:NO]; + [self.view addSubview:_mapView]; + + _button = [[UIButton alloc] initWithFrame:CGRectMake(_mapView.frame.origin.x + 100, _mapView.frame.origin.y + 45, 170, 30)]; + _button.layer.cornerRadius = 15; + _button.backgroundColor = [UIColor blueColor]; + [_button setTitle:@"Create snapshot" forState:UIControlStateNormal]; + [_button addTarget:self action:@selector(createSnapshot) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_button]; + + _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height / 2, self.view.bounds.size.width, self.view.bounds.size.height / 2)]; + _imageView.backgroundColor = [UIColor blackColor]; + _imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_imageView]; +} + +- (void)createSnapshot { + + MGLMapSnapshotOptions *options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:_mapView.styleURL camera:_mapView.camera size:_mapView.bounds.size]; + + options.zoomLevel = _mapView.zoomLevel; + + UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(_imageView.center.x - 30, _imageView.center.y - 30, 60, 60)]; + [self.view addSubview:indicator]; + [indicator startAnimating]; + + CGRect imageRect = _imageView.bounds; + + __block MGLMapSnapshotter *snapshotter = [[MGLMapSnapshotter alloc] initWithOptions:options]; + + [snapshotter startWithOverlayHandler:^(MGLMapSnapshotOverlay * _Nullable snapshotOverlay) { + // Overlays red square over snapshot (but below attribution) +// CGContextSetFillColorWithColor(snapshotOverlay.context, [UIColor.greenColor CGColor]); +// CGContextSetAlpha(snapshotOverlay.context, 0.2); +// CGContextAddRect(snapshotOverlay.context, imageRect); +// CGContextFillRect(snapshotOverlay.context, imageRect); + + // Slick drawing, but pushes attribution out of the way + CGContextSetStrokeColorWithColor(snapshotOverlay.context, [UIColor.redColor CGColor]); + CGContextTranslateCTM(snapshotOverlay.context, imageRect.size.width / 2, imageRect.size.height / 2); + BOOL first = YES; + CGFloat length = 256; + + for (int i = 1; i <= length; i++) + { + CGContextRotateCTM(snapshotOverlay.context, M_PI / 2); + + if (first) { + CGContextMoveToPoint(snapshotOverlay.context, length, 50); + first = NO; + } else { + CGContextAddLineToPoint(snapshotOverlay.context, length, 50); + } + + length *= 0.99; + } + + CGContextStrokePath(snapshotOverlay.context); + + } completionHandler:^(MGLMapSnapshot * _Nullable snapshot, NSError * _Nullable error) { + if (error != nil) { + NSLog(@"Unable to create a map snapshot."); + } else if (snapshot != nil) { + // Add the map snapshot's image to the image view. + [indicator stopAnimating]; + self.imageView.image = snapshot.image; + } + + snapshotter = nil; + }]; +} + +@end + diff --git a/platform/ios/app/Main.storyboard b/platform/ios/app/Main.storyboard index ac83bd968f..04cda22eff 100644 --- a/platform/ios/app/Main.storyboard +++ b/platform/ios/app/Main.storyboard @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14865.1" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="PSe-Ot-7Ff"> +<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="0Nh-jr-UFF"> <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14819.2"/> + <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> @@ -13,11 +13,11 @@ <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="148" 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="148" 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="82" width="40" height="20"/> @@ -38,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="148" height="200"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <accessibility key="accessibilityConfiguration"> <accessibilityTraits key="traits" notEnabled="YES"/> @@ -214,6 +214,21 @@ </objects> <point key="canvasLocation" x="2075" y="350"/> </scene> + <!--Context Snapshot View Controller--> + <scene sceneID="hFh-b6-g0M"> + <objects> + <viewController id="0Nh-jr-UFF" customClass="MBXContextSnapshotViewController" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="5Wv-sh-k8L"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> + <viewLayoutGuide key="safeArea" id="qNT-d8-dSI"/> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="Cpl-dC-mUb" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="3131" y="459"/> + </scene> <!--Navigation Controller--> <scene sceneID="LFg-oU-zTK"> <objects> diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 7712c332c4..bf575c44a8 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 071BBB031EE76146001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */; }; + 0723AB85232717AB0095FD55 /* MBXContextSnapshotViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0723AB84232717AB0095FD55 /* MBXContextSnapshotViewController.m */; }; 075AF842227B6762008D7A4C /* MBXState.m in Sources */ = {isa = PBXBuildFile; fileRef = 075AF841227B6762008D7A4C /* MBXState.m */; }; 075AF845227B67C6008D7A4C /* MBXStateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 075AF844227B67C6008D7A4C /* MBXStateManager.m */; }; 076171C32139C70900668A35 /* MGLMapViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 076171C22139C70900668A35 /* MGLMapViewTests.m */; }; @@ -868,6 +869,8 @@ 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource.h; sourceTree = "<group>"; }; 071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; }; 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLImageSourceTests.m; path = ../../darwin/test/MGLImageSourceTests.m; sourceTree = "<group>"; }; + 0723AB83232717AB0095FD55 /* MBXContextSnapshotViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBXContextSnapshotViewController.h; sourceTree = "<group>"; }; + 0723AB84232717AB0095FD55 /* MBXContextSnapshotViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBXContextSnapshotViewController.m; sourceTree = "<group>"; }; 074A7F0C2277C093001A62D1 /* insert_access_token.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = insert_access_token.sh; sourceTree = "<group>"; }; 075AF840227B6762008D7A4C /* MBXState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBXState.h; sourceTree = "<group>"; }; 075AF841227B6762008D7A4C /* MBXState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBXState.m; sourceTree = "<group>"; }; @@ -1983,6 +1986,8 @@ DA1DC94C1CB6C1C2006E619F /* Demo App */ = { isa = PBXGroup; children = ( + 0723AB83232717AB0095FD55 /* MBXContextSnapshotViewController.h */, + 0723AB84232717AB0095FD55 /* MBXContextSnapshotViewController.m */, 3E6465D52065767A00685536 /* LimeGreenStyleLayer.h */, 3E6465D42065767A00685536 /* LimeGreenStyleLayer.m */, DA1DC9501CB6C1C2006E619F /* MBXAppDelegate.h */, @@ -3248,6 +3253,7 @@ DA1DC96B1CB6C6B7006E619F /* MBXOfflinePacksTableViewController.m in Sources */, 075AF845227B67C6008D7A4C /* MBXStateManager.m in Sources */, DA1DC96A1CB6C6B7006E619F /* MBXCustomCalloutView.m in Sources */, + 0723AB85232717AB0095FD55 /* MBXContextSnapshotViewController.m in Sources */, 075AF842227B6762008D7A4C /* MBXState.m in Sources */, 927FBCFC1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m in Sources */, DA1DC99B1CB6E064006E619F /* MBXViewController.m in Sources */, diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index cbf08f7dd3..da9a179ad3 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -17,6 +17,7 @@ * Fixed a rendering issue that non-SDF icon would be treated as SDF icon if they are in the same layer. ([#15456](https://github.com/mapbox/mapbox-gl-native/pull/15456)) * Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467)) * Fixed an issue of integer overflow when converting `tileCoordinates` to `LatLon`, which caused issues such as `queryRenderedFeatures` and `querySourceFeatures` returning incorrect coordinates at zoom levels 20 and higher. ([#15560](https://github.com/mapbox/mapbox-gl-native/pull/15560)) +* Added an `-[MGLMapSnapshotter startWithOverlayHandler:completionHandler:]` method to provide the snapshot's current `CGContext` in order to perform custom drawing on `MGLMapSnapShot` objects. ([#15530](https://github.com/mapbox/mapbox-gl-native/pull/15530)) ### Styles and rendering |