summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2017-11-01 19:37:31 -0400
committerFabian Guerra Soto <fabian.guerra@mapbox.com>2017-11-07 17:56:09 -0500
commit93e363bd8c98dbdc9dca9e4be77bbee6215dc9c7 (patch)
treece0b8658c72cdd9f19527f3ed958cdcca389ea4d
parent24de48b7724cb359b3044cd691588a221dd2b550 (diff)
downloadqtlocation-mapboxgl-93e363bd8c98dbdc9dca9e4be77bbee6215dc9c7.tar.gz
[ios, macos] Add attribution to snapshots.
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.mm119
1 files changed, 117 insertions, 2 deletions
diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm
index a00521a87a..be76a30511 100644
--- a/platform/darwin/src/MGLMapSnapshotter.mm
+++ b/platform/darwin/src/MGLMapSnapshotter.mm
@@ -14,11 +14,14 @@
#import "MGLGeometry_Private.h"
#import "NSBundle+MGLAdditions.h"
#import "MGLStyle.h"
+#import "MGLAttributionInfo_Private.h"
#if TARGET_OS_IPHONE
#import "UIImage+MGLAdditions.h"
#else
#import "NSImage+MGLAdditions.h"
+#import <CoreGraphics/CoreGraphics.h>
+#import <QuartzCore/QuartzCore.h>
#endif
const CGPoint MGLLogoImagePosition = CGPointMake(8, 8);
@@ -146,6 +149,33 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
dispatch_async(queue, ^{
_snapshotCallback = std::make_unique<mbgl::Actor<mbgl::MapSnapshotter::Callback>>(*mbgl::Scheduler::GetCurrent(), [=](std::exception_ptr mbglError, mbgl::PremultipliedImage image, mbgl::MapSnapshotter::Attributions attributions, mbgl::MapSnapshotter::PointForFn pointForFn) {
_loading = false;
+
+ NSMutableArray *infos = [NSMutableArray array];
+
+#if TARGET_OS_IPHONE
+ CGFloat fontSize = [UIFont smallSystemFontSize];
+ UIColor *attributeFontColor = [UIColor blackColor];
+#else
+ CGFloat fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize];
+ NSColor *attributeFontColor = [NSColor blackColor];
+#endif
+ for (auto attribution = attributions.begin(); attribution != attributions.end(); ++attribution) {
+ NSString *attributionHTMLString = @(attribution->c_str());
+ NSArray *tileSetInfos = [MGLAttributionInfo attributionInfosFromHTMLString:attributionHTMLString
+ fontSize:fontSize
+ linkColor:attributeFontColor];
+ [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};
@@ -170,10 +200,33 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
#if TARGET_OS_IPHONE
UIImage *logoImage = [UIImage imageNamed:@"mapbox" inBundle:[NSBundle mgl_frameworkBundle] compatibleWithTraitCollection:nil];
+ CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width, logoImage.size.height);
+
+ CGPoint attributionTextPosition = CGPointMake(mglImage.size.width - 10 - attributionBackgroundSize.width,
+ logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
+
+ CGRect cropRect = CGRectMake(attributionTextPosition.x * mglImage.scale, (attributionTextPosition.y + 1) * mglImage.scale, attributionBackgroundSize.width * mglImage.scale, attributionBackgroundSize.height * mglImage.scale);
+
+
UIGraphicsBeginImageContextWithOptions(mglImage.size, NO, self.options.scale);
[mglImage drawInRect:CGRectMake(0, 0, mglImage.size.width, mglImage.size.height)];
- [logoImage drawInRect:CGRectMake(MGLLogoImagePosition.x, mglImage.size.height - (MGLLogoImagePosition.y + logoImage.size.height), logoImage.size.width,logoImage.size.height)];
+
+ [logoImage drawInRect:logoImageRect];
+
+ UIImage *currentImage = UIGraphicsGetImageFromCurrentImageContext();
+ CGImageRef attributionImageRef = CGImageCreateWithImageInRect([currentImage CGImage], cropRect);
+ UIImage *attributionImage = [UIImage imageWithCGImage:attributionImageRef];
+ CGImageRelease(attributionImageRef);
+
+ CIImage *ciAttributionImage = [[CIImage alloc] initWithCGImage:attributionImage.CGImage];
+
+ UIImage *blurredAttributionBackground = [self blurredAttributionBackground:ciAttributionImage];
+
+ [blurredAttributionBackground drawInRect:CGRectMake(attributionTextPosition.x, attributionTextPosition.y + 1, attributionBackgroundSize.width, attributionBackgroundSize.height)];
+
+ [self drawAttributionText:infos origin:CGPointMake(attributionTextPosition.x + 10, attributionTextPosition.y)];
+
UIImage *compositedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
@@ -183,6 +236,11 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
NSSize targetSize = NSMakeSize(self.options.size.width, self.options.size.height);
NSRect targetFrame = NSMakeRect(0, 0, targetSize.width, targetSize.height);
+ CGRect logoImageRect = CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width, logoImage.size.height);
+ CGPoint attributionTextPosition = CGPointMake(targetFrame.size.width - 10 - attributionBackgroundSize.width,
+ logoImageRect.origin.y + (logoImageRect.size.height / 2) - (attributionBackgroundSize.height / 2));
+
+
NSImage *compositedImage = nil;
NSImageRep *sourceImageRep = [sourceImage bestRepresentationForRect:targetFrame
context:nil
@@ -190,10 +248,26 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
compositedImage = [[NSImage alloc] initWithSize:targetSize];
[compositedImage lockFocus];
+
[sourceImageRep drawInRect: targetFrame];
- [logoImage drawInRect:CGRectMake(MGLLogoImagePosition.x, MGLLogoImagePosition.y, logoImage.size.width,logoImage.size.height)];
+
+ [logoImage drawInRect:logoImageRect];
+
+ NSRect cropRect = NSMakeRect(attributionTextPosition.x, MGLLogoImagePosition.y + 1, attributionBackgroundSize.width, attributionBackgroundSize.height);
+
+ NSBitmapImageRep *attributionBackground = [[NSBitmapImageRep alloc] initWithFocusedViewRect: cropRect];
+
+ CIImage *attributionBackgroundImage = [[CIImage alloc] initWithCGImage:[attributionBackground CGImage]];
+
+ NSImage *blurredAttributionBackground = [self blurredAttributionBackground:attributionBackgroundImage];
+
+ [blurredAttributionBackground drawInRect:CGRectMake(attributionTextPosition.x, MGLLogoImagePosition.y + 1, attributionBackgroundSize.width, attributionBackgroundSize.height)];
+
+ [self drawAttributionText:infos origin:CGPointMake(attributionTextPosition.x + 10, attributionTextPosition.y)];
+
[compositedImage unlockFocus];
+
#endif
// Dispatch result to origin queue
@@ -208,6 +282,47 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64;
});
}
+- (void)drawAttributionText:(NSArray *)attributionInfo origin:(CGPoint)origin
+{
+ for (MGLAttributionInfo *info in attributionInfo) {
+ if (info.isFeedbackLink) {
+ continue;
+ }
+ [info.title drawAtPoint:origin];
+
+ origin.x += [info.title size].width + 10;
+ }
+}
+
+- (MGLImage *)blurredAttributionBackground:(CIImage *)backgroundImage
+{
+ CGAffineTransform transform = CGAffineTransformIdentity;
+ CIFilter *clamp = [CIFilter filterWithName:@"CIAffineClamp"];
+ [clamp setValue:backgroundImage forKey:kCIInputImageKey];
+ [clamp setValue:[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"];
+
+ CIFilter *attributionBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
+ [attributionBlurFilter setValue:[clamp outputImage] forKey:kCIInputImageKey];
+ [attributionBlurFilter setValue:@10 forKey:kCIInputRadiusKey];
+
+ CIFilter *attributionColorFilter = [CIFilter filterWithName:@"CIColorControls"];
+ [attributionColorFilter setValue:[attributionBlurFilter outputImage] forKey:kCIInputImageKey];
+ [attributionColorFilter setValue:@(0.1) forKey:kCIInputBrightnessKey];
+
+ CIImage *blurredImage = attributionColorFilter.outputImage;
+
+ CIContext *ctx = [CIContext contextWithOptions:nil];
+ 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
+}
+
- (void)cancel
{
_snapshotCallback.reset();