Skip to content

Commit

Permalink
[ios, macos] Update the attribution format for small snapshots.
Browse files Browse the repository at this point in the history
  • Loading branch information
fabian-guerra committed Nov 17, 2017
1 parent 84fbb7c commit 5eb050d
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 29 deletions.
9 changes: 9 additions & 0 deletions platform/darwin/src/MGLAttributionInfo.mm
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ - (instancetype)initWithTitle:(NSAttributedString *)title URL:(NSURL *)URL {
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];
}
Expand Down
150 changes: 121 additions & 29 deletions platform/darwin/src/MGLMapSnapshotter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -61,6 +79,7 @@ - (instancetype)initWithImage:(nullable MGLImage *)image scale:(CGFloat)scale po
@implementation MGLMapSnapshot {
mbgl::MapSnapshotter::PointForFn _pointForFn;
}

- (instancetype)initWithImage:(nullable MGLImage *)image scale:(CGFloat)scale pointForFn:(mbgl::MapSnapshotter::PointForFn)pointForFn
{
self = [super init];
Expand Down Expand Up @@ -88,6 +107,7 @@ @implementation MGLMapSnapshotter {
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
Expand Down Expand Up @@ -167,15 +187,6 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshot
[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};
Expand All @@ -198,20 +209,28 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshot
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);
Expand All @@ -231,24 +250,32 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshot

[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;
Expand All @@ -261,7 +288,9 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshot

[sourceImageRep drawInRect: targetFrame];

[logoImage drawInRect:logoImageRect];
if (logoImage) {
[logoImage drawInRect:logoImageRect];
}

NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect:attributionBackgroundFrame];

Expand All @@ -271,7 +300,7 @@ - (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshot

[blurredAttributionBackground drawInRect:attributionBackgroundFrame];

[self drawAttributionText:infos origin:attributionTextPosition];
[self drawAttributionText:option.attributionInfo origin:attributionTextPosition];

[compositedImage unlockFocus];

Expand Down Expand Up @@ -323,14 +352,77 @@ - (MGLImage *)blurredAttributionBackground:(CIImage *)backgroundImage
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();
Expand Down
Binary file modified platform/ios/resources/Base.lproj/Localizable.strings
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "mapbox_helmet.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
4 changes: 4 additions & 0 deletions platform/macos/macos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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; };
Expand Down Expand Up @@ -826,6 +828,7 @@
DA8933AB1CCD290700E68420 /* Localizable.strings */,
DAE6C3BB1CC31F2E00DB3429 /* default_marker.pdf */,
DAE6C3BC1CC31F2E00DB3429 /* mapbox.pdf */,
1F9EF4051FBA1B0D0063FBB0 /* mapbox_helmet.pdf */,
DA8933A71CCD287300E68420 /* MGLAnnotationCallout.xib */,
);
name = "Kit Resources";
Expand Down Expand Up @@ -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;
};
Expand Down
Binary file modified platform/macos/sdk/Base.lproj/Localizable.strings
Binary file not shown.
Binary file added platform/macos/sdk/mapbox_helmet.pdf
Binary file not shown.

0 comments on commit 5eb050d

Please sign in to comment.