[ios, macos] Add attribution to snapshots.
This commit is contained in:
committed by
Fabian Guerra Soto
parent
24de48b772
commit
93e363bd8c
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user