[ios, macos] Update the attribution format for small snapshots.

This commit is contained in:
Fabian Guerra
2017-11-13 17:29:54 -05:00
committed by Fabian Guerra Soto
parent 84fbb7c576
commit 5eb050dc35
8 changed files with 856 additions and 29 deletions

View File

@@ -127,6 +127,15 @@
return self;
}
- (id)copyWithZone:(nullable NSZone *)zone
{
MGLAttributionInfo *info = [[[self class] allocWithZone:zone] initWithTitle:_title
URL:_URL];
info.feedbackLink = _feedbackLink;
return info;
}
- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel {
return [self feedbackURLForStyleURL:nil atCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:0 pitch:0];
}

View File

@@ -27,6 +27,24 @@
const CGPoint MGLLogoImagePosition = CGPointMake(8, 8);
const CGFloat MGLSnapshotterMinimumPixelSize = 64;
@interface MGLSnapshotAttributionOptions : NSObject
#if TARGET_OS_IPHONE
@property (nonatomic) UIImage *logoImage;
#else
@property (nonatomic) NSImage *logoImage;
#endif
@property (nonatomic) CGSize attributionBackgroundSize;
@property (nonatomic) NS_ARRAY_OF(MGLAttributionInfo *) *attributionInfo;
@end
@implementation MGLSnapshotAttributionOptions
@end
@implementation MGLMapSnapshotOptions
- (instancetype _Nonnull)initWithStyleURL:(nullable NSURL *)styleURL camera:(MGLMapCamera *)camera size:(CGSize) size
@@ -61,6 +79,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
@implementation MGLMapSnapshot {
mbgl::MapSnapshotter::PointForFn _pointForFn;
}
- (instancetype)initWithImage:(nullable MGLImage *)image scale:(CGFloat)scale pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn
{
self = [super init];
@@ -88,6 +107,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
std::shared_ptr<mbgl::ThreadPool> _mbglThreadPool;
std::unique_ptr<mbgl::MapSnapshotter> _mbglMapSnapshotter;
std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> _snapshotCallback;
CGFloat _defaultLogoHeight;
}
- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options
@@ -167,15 +187,6 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
}
CGSize attributionBackgroundSize = CGSizeMake(10, 0);
for (MGLAttributionInfo *info in infos) {
if (info.isFeedbackLink) {
continue;
}
attributionBackgroundSize.width += [info.title size].width + 10;
attributionBackgroundSize.height = MAX([info.title size].height, attributionBackgroundSize.height);
}
if (mbglError) {
NSString *description = @(mbgl::util::toString(mbglError).c_str());
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
@@ -198,20 +209,28 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(workQueue, ^{
#if TARGET_OS_IPHONE
UIImage *logoImage = [UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
MGLSnapshotAttributionOptions *option = [self attributionOptionsForSize:mglImage.size attributionInfo:infos];
UIImage *logoImage = option.logoImage;
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
CGRect attributionBackgroundFrame = CGRectMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1,
attributionBackgroundSize.width,
attributionBackgroundSize.height);
CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - option.attributionBackgroundSize.width,
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (option.attributionBackgroundSize.height / 2) + 1);
if (!logoImage) {
logoImageRect = CGRectMake(0, mglImage.size.height - (MGLLogoImagePosition.y + _defaultLogoHeight), 0, _defaultLogoHeight);
attributionOrigin = CGPointMake(10, logoImageRect.origin.y + (logoImageRect.size.height / 2) - (option.attributionBackgroundSize.height / 2) + 1);
}
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
attributionOrigin.y,
option.attributionBackgroundSize.width,
option.attributionBackgroundSize.height);
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
attributionBackgroundFrame.origin.y - 1);
CGRect cropRect = CGRectMake(attributionBackgroundFrame.origin.x * mglImage.scale,
attributionBackgroundFrame.origin.y * mglImage.scale,
attributionBackgroundSize.width * mglImage.scale,
attributionBackgroundSize.height * mglImage.scale);
option.attributionBackgroundSize.width * mglImage.scale,
option.attributionBackgroundSize.height * mglImage.scale);
UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
@@ -231,24 +250,32 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
[self drawAttributionText:infos origin:attributionTextPosition];
[self drawAttributionText:option.attributionInfo origin:attributionTextPosition];
UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
#else
NSImage *logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox" ofType:@"pdf"]];
NSImage *sourceImage = mglImage;
NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
MGLSnapshotAttributionOptions *option = [self attributionOptionsForSize:targetSize attributionInfo:infos];
NSImage *logoImage = option.logoImage;
NSImage *sourceImage = mglImage;
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
CGRect attributionBackgroundFrame = CGRectMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
MGLLogoImagePosition.y + 1,
attributionBackgroundSize.width,
attributionBackgroundSize.height);
CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - option.attributionBackgroundSize.width,
MGLLogoImagePosition.y + 1);
if (!logoImage) {
logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, _defaultLogoHeight);
attributionOrigin = CGPointMake(10, attributionOrigin.y);
}
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
attributionOrigin.y,
option.attributionBackgroundSize.width,
option.attributionBackgroundSize.height);
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
logoImageRect.origin.y + (logoImageRect.size.height / 2) - (option.attributionBackgroundSize.height / 2));
NSImage *compositedImage = nil;
@@ -261,7 +288,9 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[sourceImageRep drawInRect: targetFrame];
[logoImage drawInRect:logoImageRect];
if (logoImage) {
[logoImage drawInRect:logoImageRect];
}
NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect:attributionBackgroundFrame];
@@ -271,7 +300,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
[self drawAttributionText:infos origin:attributionTextPosition];
[self drawAttributionText:option.attributionInfo origin:attributionTextPosition];
[compositedImage unlockFocus];
@@ -323,14 +352,77 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
CGImageRef cgimg = [ctx createCGImage:blurredImage fromRect:[backgroundImage extent]];
#if TARGET_OS_IPHONE
return [UIImage imageWithCGImage:cgimg];
#else
return [[NSImage alloc] initWithCGImage:cgimg size:[backgroundImage extent].size];
#endif
}
- (MGLSnapshotAttributionOptions *)attributionOptionsForSize:(CGSize)snapshotSize attributionInfo:(NSArray *)attributionInfo
{
NSMutableArray *options = [NSMutableArray array];
MGLSnapshotAttributionOptions *largeLogoAttribution = [self attributionOptionsForAttributionInfo:attributionInfo abbreviated:NO];
#if TARGET_OS_IPHONE
largeLogoAttribution.logoImage = [UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
#else
largeLogoAttribution.logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox" ofType:@"pdf"]];
#endif
_defaultLogoHeight = largeLogoAttribution.logoImage.size.height;
MGLSnapshotAttributionOptions *smallLogoAttribution = [self attributionOptionsForAttributionInfo:attributionInfo abbreviated:NO];
#if TARGET_OS_IPHONE
smallLogoAttribution.logoImage = [UIImage imageNamed:@"mapbox_helmet" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
#else
smallLogoAttribution.logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox_helmet" ofType:@"pdf"]];
#endif
MGLSnapshotAttributionOptions *noLogoAttribution = [self attributionOptionsForAttributionInfo:attributionInfo abbreviated:YES];
[options addObject:largeLogoAttribution];
[options addObject:smallLogoAttribution];
[options addObject:noLogoAttribution];
for (MGLSnapshotAttributionOptions *attributionOptions in options) {
// -[Mapbox Logo]-[Attribution Background]-
CGFloat origin = attributionOptions.logoImage ? MGLLogoImagePosition.x : 0;
CGFloat width = origin + attributionOptions.logoImage.size.width + 10 + attributionOptions.attributionBackgroundSize.width + 10;
if (width <= snapshotSize.width) {
return attributionOptions;
}
}
return noLogoAttribution;
}
- (MGLSnapshotAttributionOptions *)attributionOptionsForAttributionInfo:(NSArray *)attributionInfo abbreviated:(BOOL)isAbbreviated
{
NSString *openStreetMap = NSLocalizedStringWithDefaultValue(@"OSM_FULL_NAME", nil, nil, @"OpenStreetMap", @"OpenStreetMap full name attribution");
NSString *OSM = NSLocalizedStringWithDefaultValue(@"OSM_SHORT_NAME", nil, nil, @"OSM", @"OpenStreetMap short name attribution");
NSMutableArray *infos = [NSMutableArray array];
CGSize attributionBackgroundSize = CGSizeMake(10, 0);
for (MGLAttributionInfo *info in attributionInfo) {
if (info.isFeedbackLink) {
continue;
}
MGLAttributionInfo *attribution = [info copy];
NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithAttributedString:info.title];
[title removeAttribute:NSUnderlineStyleAttributeName range:NSMakeRange(0, [title.string length])];
if ([title.string rangeOfString:@"OpenStreetMap"].location != NSNotFound) {
[title.mutableString replaceOccurrencesOfString:@"OpenStreetMap" withString:isAbbreviated ? OSM : openStreetMap options:NSCaseInsensitiveSearch range:NSMakeRange(0, [title.mutableString length])];
}
attribution.title = title;
attributionBackgroundSize.width += [attribution.title size].width + 10;
attributionBackgroundSize.height = MAX([attribution.title size].height, attributionBackgroundSize.height);
[infos addObject:attribution];
}
MGLSnapshotAttributionOptions *attributionOptions = [[MGLSnapshotAttributionOptions alloc] init];
attributionOptions.attributionBackgroundSize = attributionBackgroundSize;
attributionOptions.attributionInfo = infos;
return attributionOptions;
}
- (void)cancel
{
_snapshotCallback.reset();

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "mapbox_helmet.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

File diff suppressed because one or more lines are too long

View File

@@ -16,6 +16,7 @@
1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A21ECFB00300021D39 /* MGLLight.mm */; };
1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */; };
1F95931B1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */; };
1F9EF4061FBA1B0E0063FBB0 /* mapbox_helmet.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 1F9EF4051FBA1B0D0063FBB0 /* mapbox_helmet.pdf */; };
1FCDF1421F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FCDF1401F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h */; };
1FCDF1431F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FCDF1411F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m */; };
30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */; };
@@ -289,6 +290,7 @@
1F7454A21ECFB00300021D39 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLightTest.mm; sourceTree = "<group>"; };
1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = "<group>"; };
1F9EF4051FBA1B0D0063FBB0 /* mapbox_helmet.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = mapbox_helmet.pdf; sourceTree = "<group>"; };
1FCDF1401F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLVectorSource+MGLAdditions.h"; sourceTree = "<group>"; };
1FCDF1411F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLVectorSource+MGLAdditions.m"; sourceTree = "<group>"; };
30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSImage+MGLAdditions.h"; path = "src/NSImage+MGLAdditions.h"; sourceTree = SOURCE_ROOT; };
@@ -826,6 +828,7 @@
DA8933AB1CCD290700E68420 /* Localizable.strings */,
DAE6C3BB1CC31F2E00DB3429 /* default_marker.pdf */,
DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */,
1F9EF4051FBA1B0D0063FBB0 /* mapbox_helmet.pdf */,
DA8933A71CCD287300E68420 /* MGLAnnotationCallout.xib */,
);
name = "Kit Resources";
@@ -1400,6 +1403,7 @@
DA8933A51CCD287300E68420 /* MGLAnnotationCallout.xib in Resources */,
DA8933B51CCD2C2500E68420 /* Foundation.strings in Resources */,
DA8933B81CCD2C2D00E68420 /* Foundation.stringsdict in Resources */,
1F9EF4061FBA1B0E0063FBB0 /* mapbox_helmet.pdf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

File diff suppressed because one or more lines are too long