summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2017-11-21 16:32:05 -0500
committerFabian Guerra <fabian.guerra@mapbox.com>2017-12-01 10:10:49 -0500
commitae9d793d1c0ae5d0a5a6808653b3005dd16dbe60 (patch)
tree6a5f15b4ce454e5c97929d8b2b8f9372a4ac8b53
parent5086c76997fdc073816632688da2e8850aff510b (diff)
downloadqtlocation-mapboxgl-upstream/fabian-refactor-10490.tar.gz
[ios, macos] Refactor snapshot attribution.upstream/fabian-refactor-10490
-rw-r--r--platform/darwin/src/MGLAttributionInfo.h31
-rw-r--r--platform/darwin/src/MGLAttributionInfo.mm19
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm180
3 files changed, 144 insertions, 86 deletions
diff --git a/platform/darwin/src/MGLAttributionInfo.h b/platform/darwin/src/MGLAttributionInfo.h
index 031a10060f..2e2967a6c6 100644
--- a/platform/darwin/src/MGLAttributionInfo.h
+++ b/platform/darwin/src/MGLAttributionInfo.h
@@ -8,6 +8,24 @@
NS_ASSUME_NONNULL_BEGIN
/**
+ The attribution info is represented in the longest format available.
+ */
+typedef NS_ENUM(NSUInteger, MGLAttributionInfoStyle) {
+ /**
+ Specifies a short attribution info style.
+ */
+ MGLAttributionInfoStyleShort = 1,
+ /**
+ Specifies a medium attribution info style.
+ */
+ MGLAttributionInfoStyleMedium,
+ /**
+ Specifies a long attribution info style.
+ */
+ MGLAttributionInfoStyleLong
+};
+
+/**
Information about an attribution statement, usually a copyright or trademark
statement, associated with a map content source.
*/
@@ -59,6 +77,19 @@ MGL_EXPORT
*/
- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel;
+/**
+ Returns a copy of the current `title` formatted accordingly to `style`.
+
+ Example: If `style` = `MGLAttributionInfoStyleShort` and
+ `MGLAttributionInfo.title` = `OpenStreetMap` then it will format
+ `MGLAttributionInfo.title` = `OSM`
+
+ @param style The attribution info style.
+
+ @return The `NSAttributedString` styled title.
+ */
+- (NSAttributedString *)titleWithStyle:(MGLAttributionInfoStyle)style;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm
index 92fb9b689f..29dd5229a7 100644
--- a/platform/darwin/src/MGLAttributionInfo.mm
+++ b/platform/darwin/src/MGLAttributionInfo.mm
@@ -168,6 +168,25 @@
return components.URL;
}
+- (NSAttributedString *)titleWithStyle:(MGLAttributionInfoStyle)style
+{
+ 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");
+
+ NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithAttributedString:self.title];
+ [title removeAttribute:NSUnderlineStyleAttributeName range:NSMakeRange(0, [title.string length])];
+
+ BOOL isAbbreviated = (style == MGLAttributionInfoStyleShort);
+
+ if ([title.string rangeOfString:@"OpenStreetMap"].location != NSNotFound) {
+ [title.mutableString replaceOccurrencesOfString:@"OpenStreetMap" withString:isAbbreviated ? OSM : openStreetMap
+ options:NSCaseInsensitiveSearch
+ range:NSMakeRange(0, [title.mutableString length])];
+ }
+
+ return title;
+}
+
- (BOOL)isEqual:(id)object {
return [object isKindOfClass:[self class]] && [[object title] isEqual:self.title] && [[object URL] isEqual:self.URL];
}
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index 31b3ed41d6..8b54488814 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -27,24 +27,6 @@
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
@@ -107,7 +89,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;
+ NS_ARRAY_OF(MGLAttributionInfo *) *_attributionInfo;
}
- (instancetype)initWithOptions:(MGLMapSnapshotOptions *)options
@@ -187,6 +169,8 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[infos growArrayByAddingAttributionInfosFromArray:tileSetInfos];
}
+ _attributionInfo = infos;
+
if (mbglError) {
NSString *description = @(mbgl::util::toString(mbglError).c_str());
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
@@ -209,28 +193,38 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(workQueue, ^{
#if TARGET_OS_IPHONE
- MGLSnapshotAttributionOptions *option = [self attributionOptionsForSize:mglImage.size attributionInfo:infos];
- UIImage *logoImage = option.logoImage;
+ MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
+ for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
+ attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
+ CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
+ if (attributionSize.width <= mglImage.size.width) {
+ break;
+ }
+ }
+
+ UIImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
+ CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
- CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - option.attributionBackgroundSize.width,
- logoImageRect.origin.y + (logoImageRect.size.height / 2) - (option.attributionBackgroundSize.height / 2) + 1);
+ CGPoint attributionOrigin = CGPointMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
+ logoImageRect.origin.y + (logoImageRect.size.height / 2) - (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);
+ CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
+ logoImageRect = CGRectMake(0, mglImage.size.height - (MGLLogoImagePosition.y + defaultLogoSize.height), 0, defaultLogoSize.height);
+ attributionOrigin = CGPointMake(10, logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2) + 1);
}
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
attributionOrigin.y,
- option.attributionBackgroundSize.width,
- option.attributionBackgroundSize.height);
+ attributionBackgroundSize.width,
+ 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,
- option.attributionBackgroundSize.width * mglImage.scale,
- option.attributionBackgroundSize.height * mglImage.scale);
+ attributionBackgroundSize.width * mglImage.scale,
+ attributionBackgroundSize.height * mglImage.scale);
UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
@@ -250,7 +244,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
- [self drawAttributionText:option.attributionInfo origin:attributionTextPosition];
+ [self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
@@ -258,24 +252,35 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
#else
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;
+
+ MGLAttributionInfoStyle attributionInfoStyle = MGLAttributionInfoStyleLong;
+ for (NSUInteger styleValue = MGLAttributionInfoStyleLong; styleValue >= MGLAttributionInfoStyleShort; styleValue--) {
+ attributionInfoStyle = (MGLAttributionInfoStyle)styleValue;
+ CGSize attributionSize = [self attributionSizeWithLogoStyle:attributionInfoStyle sourceAttributionStyle:attributionInfoStyle];
+ if (attributionSize.width <= mglImage.size.width) {
+ break;
+ }
+ }
+
+ NSImage *logoImage = [self logoImageWithStyle:attributionInfoStyle];
+ CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionInfoStyle];
NSImage *sourceImage = mglImage;
CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
- CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - option.attributionBackgroundSize.width,
+ CGPoint attributionOrigin = CGPointMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
MGLLogoImagePosition.y + 1);
if (!logoImage) {
- logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, _defaultLogoHeight);
+ CGSize defaultLogoSize = [self mapboxLongStyleLogo].size;
+ logoImageRect = CGRectMake(0, MGLLogoImagePosition.y, 0, defaultLogoSize.height);
attributionOrigin = CGPointMake(10, attributionOrigin.y);
}
CGRect attributionBackgroundFrame = CGRectMake(attributionOrigin.x,
attributionOrigin.y,
- option.attributionBackgroundSize.width,
- option.attributionBackgroundSize.height);
+ attributionBackgroundSize.width,
+ attributionBackgroundSize.height);
CGPoint attributionTextPosition = CGPointMake(attributionBackgroundFrame.origin.x + 10,
- logoImageRect.origin.y + (logoImageRect.size.height / 2) - (option.attributionBackgroundSize.height / 2));
+ logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
NSImage *compositedImage = nil;
@@ -300,7 +305,7 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
[blurredAttributionBackground drawInRect:attributionBackgroundFrame];
- [self drawAttributionText:option.attributionInfo origin:attributionTextPosition];
+ [self drawAttributionTextWithStyle:attributionInfoStyle origin:attributionTextPosition];
[compositedImage unlockFocus];
@@ -319,15 +324,16 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
});
}
-- (void)drawAttributionText:(NSArray *)attributionInfo origin:(CGPoint)origin
+- (void)drawAttributionTextWithStyle:(MGLAttributionInfoStyle)attributionInfoStyle origin:(CGPoint)origin
{
- for (MGLAttributionInfo *info in attributionInfo) {
+ for (MGLAttributionInfo *info in _attributionInfo) {
if (info.isFeedbackLink) {
continue;
}
- [info.title drawAtPoint:origin];
+ NSAttributedString *attribution = [info titleWithStyle:attributionInfoStyle];
+ [attribution drawAtPoint:origin];
- origin.x += [info.title size].width + 10;
+ origin.x += [attribution size].width + 10;
}
}
@@ -350,77 +356,79 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
CIContext *ctx = [CIContext contextWithOptions:nil];
CGImageRef cgimg = [ctx createCGImage:blurredImage fromRect:[backgroundImage extent]];
+ MGLImage *image;
#if TARGET_OS_IPHONE
- return [UIImage imageWithCGImage:cgimg];
+ image = [UIImage imageWithCGImage:cgimg];
#else
- return [[NSImage alloc] initWithCGImage:cgimg size:[backgroundImage extent].size];
+ image = [[NSImage alloc] initWithCGImage:cgimg size:[backgroundImage extent].size];
#endif
+ CGImageRelease(cgimg);
+ return image;
}
-- (MGLSnapshotAttributionOptions *)attributionOptionsForSize:(CGSize)snapshotSize attributionInfo:(NSArray *)attributionInfo
+- (MGLImage *)logoImageWithStyle:(MGLAttributionInfoStyle)style
{
- NSMutableArray *options = [NSMutableArray array];
- MGLSnapshotAttributionOptions *largeLogoAttribution = [self attributionOptionsForAttributionInfo:attributionInfo abbreviated:NO];
+ MGLImage *logoImage;
+ switch (style) {
+ case MGLAttributionInfoStyleLong:
+ logoImage = [self mapboxLongStyleLogo];
+ break;
+ case MGLAttributionInfoStyleMedium:
#if TARGET_OS_IPHONE
- largeLogoAttribution.logoImage = [UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
+ logoImage = [UIImage imageNamed:@"mapbox_helmet" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
#else
- largeLogoAttribution.logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox" ofType:@"pdf"]];
+ logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox_helmet" ofType:@"pdf"]];
#endif
- _defaultLogoHeight = largeLogoAttribution.logoImage.size.height;
-
- MGLSnapshotAttributionOptions *smallLogoAttribution = [self attributionOptionsForAttributionInfo:attributionInfo abbreviated:NO];
+ break;
+ case MGLAttributionInfoStyleShort:
+ logoImage = nil;
+ break;
+ }
+ return logoImage;
+}
+
+- (MGLImage *)mapboxLongStyleLogo
+{
+ MGLImage *logoImage;
#if TARGET_OS_IPHONE
- smallLogoAttribution.logoImage = [UIImage imageNamed:@"mapbox_helmet" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
+ logoImage =[UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
#else
- smallLogoAttribution.logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox_helmet" ofType:@"pdf"]];
+ logoImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mgl_frameworkBundle] pathForResource:@"mapbox" ofType:@"pdf"]];
#endif
+ return logoImage;
+}
+
+- (CGSize)attributionSizeWithLogoStyle:(MGLAttributionInfoStyle)logoStyle sourceAttributionStyle:(MGLAttributionInfoStyle)attributionStyle
+{
+ MGLImage *logoImage = [self logoImageWithStyle:logoStyle];
- MGLSnapshotAttributionOptions *noLogoAttribution = [self attributionOptionsForAttributionInfo:attributionInfo abbreviated:YES];
+ CGSize attributionBackgroundSize = [self attributionTextSizeWithStyle:attributionStyle];
- [options addObject:largeLogoAttribution];
- [options addObject:smallLogoAttribution];
- [options addObject:noLogoAttribution];
+ CGSize attributionSize = CGSizeZero;
- 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;
- }
+ if (logoImage) {
+ attributionSize.width = MGLLogoImagePosition.x + logoImage.size.width + 10;
}
+ attributionSize.width = attributionSize.width + 10 + attributionBackgroundSize.width + 10;
+ attributionSize.height = MAX(logoImage.size.height, attributionBackgroundSize.height);
- return noLogoAttribution;
+ return attributionSize;
}
-- (MGLSnapshotAttributionOptions *)attributionOptionsForAttributionInfo:(NSArray *)attributionInfo abbreviated:(BOOL)isAbbreviated
+- (CGSize)attributionTextSizeWithStyle:(MGLAttributionInfoStyle)attributionStyle
{
- 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) {
+ 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];
+ CGSize attributionSize = [info titleWithStyle:attributionStyle].size;
+ attributionBackgroundSize.width += attributionSize.width + 10;
+ attributionBackgroundSize.height = MAX(attributionSize.height, attributionBackgroundSize.height);
}
- MGLSnapshotAttributionOptions *attributionOptions = [[MGLSnapshotAttributionOptions alloc] init];
- attributionOptions.attributionBackgroundSize = attributionBackgroundSize;
- attributionOptions.attributionInfo = infos;
-
- return attributionOptions;
+ return attributionBackgroundSize;
}
- (void)cancel