summaryrefslogtreecommitdiff
path: root/platform/ios/src
diff options
context:
space:
mode:
authorRoman Blum <rmnblm@gmail.com>2016-10-12 21:30:20 +0200
committerMinh Nguyễn <mxn@1ec5.org>2016-10-12 12:30:20 -0700
commita24e559ac83a47d19e28290c7ded427adeb303a3 (patch)
tree930c91599bea3b6a524559ba900fb42b8b034f98 /platform/ios/src
parent7bbf4a286e36ac26e7fa7317bd7942b5163c1188 (diff)
downloadqtlocation-mapboxgl-a24e559ac83a47d19e28290c7ded427adeb303a3.tar.gz
[ios, macos] possibility to set custom images to style (#6637)
* [ios, macos] possibility to set custom images to style * [ios, macos] setImage:forName now supports MGLImage (UIImage/NSImage) * [ios, macos] update documentation for setImage:forName: and removeImageForName: * [ios, macos] rename method and fix prefix * [ios, macos] change header visibility to project * [ios, macos] update header imports * [ios, macos] delete unnecessary whitespaces * [ios, macos] remove unnecessary nil checks * [ios, macos] delete unnecessary whitespaces * [ios, macos] update documentation * [ios, macos] make mgl_spriteImage a parameter-less instance method * [ios, macos] add asserts
Diffstat (limited to 'platform/ios/src')
-rw-r--r--platform/ios/src/MGLMapView.mm387
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.h9
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.mm27
3 files changed, 221 insertions, 202 deletions
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 8b58fbaf65..d0c95d9c0c 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -38,6 +38,7 @@
#import "NSProcessInfo+MGLAdditions.h"
#import "NSException+MGLAdditions.h"
#import "NSURL+MGLAdditions.h"
+#import "UIImage+MGLAdditions.h"
#import "MGLFaux3DUserLocationAnnotationView.h"
#import "MGLUserLocationAnnotationView.h"
@@ -257,16 +258,16 @@ public:
{
mbgl::Map *_mbglMap;
MBGLView *_mbglView;
-
+
BOOL _opaque;
NS_MUTABLE_ARRAY_OF(NSURL *) *_bundledStyleURLs;
-
+
MGLAnnotationContextMap _annotationContextsByAnnotationTag;
/// Tag of the selected annotation. If the user location annotation is selected, this ivar is set to `MGLAnnotationTagNotFound`.
MGLAnnotationTag _selectedAnnotationTag;
NS_MUTABLE_DICTIONARY_OF(NSString *, NS_MUTABLE_ARRAY_OF(MGLAnnotationView *) *) *_annotationViewReuseQueueByIdentifier;
-
+
BOOL _userLocationAnnotationIsSelected;
/// Size of the rectangle formed by unioning the maximum slop area around every annotation image and annotation image view.
CGSize _unionedAnnotationRepresentationSize;
@@ -283,18 +284,18 @@ public:
CADisplayLink *_displayLink;
BOOL _needsDisplayRefresh;
-
+
NSUInteger _changeDelimiterSuppressionDepth;
-
+
/// Center coordinate of the pinch gesture on the previous iteration of the gesture.
CLLocationCoordinate2D _previousPinchCenterCoordinate;
NSUInteger _previousPinchNumberOfTouches;
-
+
BOOL _delegateHasAlphasForShapeAnnotations;
BOOL _delegateHasStrokeColorsForShapeAnnotations;
BOOL _delegateHasFillColorsForShapeAnnotations;
BOOL _delegateHasLineWidthsForShapeAnnotations;
-
+
MGLCompassDirectionFormatter *_accessibilityCompassFormatter;
}
@@ -381,14 +382,14 @@ public:
self.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction | UIAccessibilityTraitAdjustable;
_accessibilityCompassFormatter = [[MGLCompassDirectionFormatter alloc] init];
_accessibilityCompassFormatter.unitStyle = NSFormattingUnitStyleLong;
-
+
self.backgroundColor = [UIColor clearColor];
self.clipsToBounds = YES;
// setup mbgl view
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
_mbglView = new MBGLView(self, scaleFactor);
-
+
// Delete the pre-offline ambient cache at ~/Library/Caches/cache.db.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *fileCachePath = [paths.firstObject stringByAppendingPathComponent:@"cache.db"];
@@ -416,7 +417,7 @@ public:
_isWaitingForRedundantReachableNotification = YES;
}
[reachability startNotifier];
-
+
// Set up annotation management and selection state.
_annotationImagesByIdentifier = [NSMutableDictionary dictionary];
_annotationContextsByAnnotationTag = {};
@@ -581,7 +582,7 @@ public:
UIImage *scaleImage = [MGLMapView resourceImageNamed:@"Compass.png"];
UIGraphicsBeginImageContextWithOptions(scaleImage.size, NO, [UIScreen mainScreen].scale);
[scaleImage drawInRect:{ CGPointZero, scaleImage.size }];
-
+
CGFloat northSize = 9;
UIFont *northFont;
if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)])
@@ -600,7 +601,7 @@ public:
scaleImage.size.height * 0.45,
north.size.width, north.size.height);
[north drawInRect:stringRect];
-
+
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
@@ -627,14 +628,14 @@ public:
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_attributionButton removeObserver:self forKeyPath:@"hidden"];
-
+
// Removing the annotations unregisters any outstanding KVO observers.
NSArray *annotations = self.annotations;
if (annotations)
{
[self removeAnnotations:annotations];
}
-
+
[self validateDisplayLink];
if (_mbglMap)
@@ -665,7 +666,7 @@ public:
if (_delegate == delegate) return;
_delegate = delegate;
-
+
_delegateHasAlphasForShapeAnnotations = [_delegate respondsToSelector:@selector(mapView:alphaForShapeAnnotation:)];
_delegateHasStrokeColorsForShapeAnnotations = [_delegate respondsToSelector:@selector(mapView:strokeColorForShapeAnnotation:)];
_delegateHasFillColorsForShapeAnnotations = [_delegate respondsToSelector:@selector(mapView:fillColorForPolygonAnnotation:)];
@@ -703,7 +704,7 @@ public:
{
return;
}
-
+
CGFloat zoomFactor = self.maximumZoomLevel - self.minimumZoomLevel + 1;
CGFloat cpuFactor = [NSProcessInfo processInfo].processorCount;
CGFloat memoryFactor = (CGFloat)[NSProcessInfo processInfo].physicalMemory / 1000 / 1000 / 1000;
@@ -795,7 +796,7 @@ public:
//
[constraintParentView removeConstraints:self.logoViewConstraints];
[self.logoViewConstraints removeAllObjects];
-
+
[self.logoViewConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeBottom
@@ -819,7 +820,7 @@ public:
//
[constraintParentView removeConstraints:self.attributionButtonConstraints];
[self.attributionButtonConstraints removeAllObjects];
-
+
[self.attributionButtonConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeBottom
@@ -867,7 +868,7 @@ public:
- (void)layoutSubviews
{
[super layoutSubviews];
-
+
[self adjustContentInset];
if ( ! _isTargetingInterfaceBuilder)
@@ -885,7 +886,7 @@ public:
[self updateHeadingForDeviceOrientation];
[self updateCompass];
}
-
+
[self updateUserLocationAnnotationView];
}
@@ -907,12 +908,12 @@ public:
// This map view is an immediate child of a view controller’s content view.
viewController = (UIViewController *)self.superview.nextResponder;
}
-
+
if ( ! viewController.automaticallyAdjustsScrollViewInsets)
{
return;
}
-
+
UIEdgeInsets contentInset = UIEdgeInsetsZero;
CGPoint topPoint = CGPointMake(0, viewController.topLayoutGuide.length);
contentInset.top = [self convertPoint:topPoint fromView:viewController.view].y;
@@ -939,14 +940,14 @@ public:
{
return;
}
-
+
// After adjusting the content inset, move the center coordinate from the
// old frame of reference to the new one represented by the newly set
// content inset.
CLLocationCoordinate2D oldCenter = self.centerCoordinate;
-
+
_contentInset = contentInset;
-
+
if (self.userTrackingMode == MGLUserTrackingModeNone)
{
// Don’t call -setCenterCoordinate:, which resets the user tracking mode.
@@ -956,7 +957,7 @@ public:
{
[self didUpdateLocationWithUserTrackingAnimated:animated];
}
-
+
// Compass, logo and attribution button constraints needs to be updated.
[self setNeedsUpdateConstraints];
}
@@ -1016,7 +1017,7 @@ public:
{
_mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
}
-
+
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateFromDisplayLink)];
_displayLink.frameInterval = MGLTargetFrameInterval;
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
@@ -1053,7 +1054,7 @@ public:
[self validateLocationServices];
[MGLMapboxEvents flush];
-
+
_displayLink.paused = YES;
if ( ! self.glSnapshotView)
@@ -1094,11 +1095,11 @@ public:
[self.glSnapshotView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.glView bindDrawable];
-
+
_displayLink.paused = NO;
[self validateLocationServices];
-
+
[MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{}];
}
}
@@ -1179,7 +1180,7 @@ public:
[self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
self.userTrackingMode = MGLUserTrackingModeNone;
-
+
[self notifyGestureDidBegin];
}
else if (pan.state == UIGestureRecognizerStateChanged)
@@ -1228,7 +1229,7 @@ public:
if (_mbglMap->getZoom() <= _mbglMap->getMinZoom() && pinch.scale < 1) return;
_mbglMap->cancelTransitions();
-
+
CGPoint centerPoint = [self anchorPointForGesture:pinch];
if (pinch.state == UIGestureRecognizerStateBegan)
@@ -1236,7 +1237,7 @@ public:
[self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
self.scale = _mbglMap->getScale();
-
+
[self notifyGestureDidBegin];
}
else if (pinch.state == UIGestureRecognizerStateChanged)
@@ -1244,9 +1245,9 @@ public:
CGFloat newScale = self.scale * pinch.scale;
if (log2(newScale) < _mbglMap->getMinZoom()) return;
-
+
_mbglMap->setScale(newScale, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
-
+
// The gesture recognizer only reports the gesture’s current center
// point, so use the previous center point to anchor the transition.
// If the number of touches has changed, the remembered center point is
@@ -1300,7 +1301,7 @@ public:
[self unrotateIfNeededForGesture];
}
-
+
_previousPinchCenterCoordinate = [self convertPoint:centerPoint toCoordinateFromView:self];
_previousPinchNumberOfTouches = pinch.numberOfTouches;
}
@@ -1310,7 +1311,7 @@ public:
if ( ! self.isRotateEnabled) return;
_mbglMap->cancelTransitions();
-
+
CGPoint centerPoint = [self anchorPointForGesture:rotate];
if (rotate.state == UIGestureRecognizerStateBegan)
@@ -1323,7 +1324,7 @@ public:
{
self.userTrackingMode = MGLUserTrackingModeFollow;
}
-
+
[self notifyGestureDidBegin];
}
else if (rotate.state == UIGestureRecognizerStateChanged)
@@ -1337,7 +1338,7 @@ public:
newDegrees = fminf(newDegrees, 30);
newDegrees = fmaxf(newDegrees, -30);
}
-
+
_mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
@@ -1378,7 +1379,7 @@ public:
return;
}
[self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap];
-
+
if (self.mapViewProxyAccessibilityElement.accessibilityElementIsFocused)
{
id nextElement;
@@ -1433,7 +1434,7 @@ public:
}
}
}
-
+
MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:tapPoint persistingResults:YES];
if (hitAnnotationTag != MGLAnnotationTagNotFound)
{
@@ -1514,7 +1515,7 @@ public:
self.scale = _mbglMap->getScale();
self.quickZoomStart = [quickZoom locationInView:quickZoom.view].y;
-
+
[self notifyGestureDidBegin];
}
else if (quickZoom.state == UIGestureRecognizerStateChanged)
@@ -1524,7 +1525,7 @@ public:
CGFloat newZoom = log2f(self.scale) + (distance / 75);
if (newZoom < _mbglMap->getMinZoom()) return;
-
+
CGPoint centerPoint = [self anchorPointForGesture:quickZoom];
_mbglMap->scaleBy(powf(2, newZoom) / _mbglMap->getScale(),
@@ -1557,7 +1558,7 @@ public:
CGFloat slowdown = 20.0;
CGFloat pitchNew = currentPitch - (gestureDistance / slowdown);
-
+
CGPoint centerPoint = [self anchorPointForGesture:twoFingerDrag];
_mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
@@ -1582,7 +1583,7 @@ public:
{
return self.contentCenter;
}
-
+
return [gesture locationInView:gesture.view];
}
@@ -1690,7 +1691,7 @@ public:
nil];
}
-
+
[self.attributionSheet showFromRect:self.attributionButton.frame inView:self animated:YES];
}
@@ -1791,7 +1792,7 @@ public:
// Redundantly move the associated annotation view outside the scope of the animation-less transaction block in -updateAnnotationViews.
annotationContext.annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
}
-
+
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
NSString *symbolName = annotationImage.styleIconIdentifier;
@@ -1968,14 +1969,14 @@ public:
- (UIBezierPath *)accessibilityPath
{
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.accessibilityFrame];
-
+
// Exclude any visible annotation callout view.
if (self.calloutViewForSelectedAnnotation)
{
UIBezierPath *calloutViewPath = [UIBezierPath bezierPathWithRect:self.calloutViewForSelectedAnnotation.frame];
[path appendPath:calloutViewPath];
}
-
+
return path;
}
@@ -2016,7 +2017,7 @@ public:
return nil;
}
std::vector<MGLAnnotationTag> visibleAnnotations = [self annotationTagsInRect:self.bounds];
-
+
// Ornaments
if (index == 0)
{
@@ -2034,7 +2035,7 @@ public:
{
return self.attributionButton;
}
-
+
std::sort(visibleAnnotations.begin(), visibleAnnotations.end());
CGPoint centerPoint = self.contentCenter;
if (self.userTrackingMode != MGLUserTrackingModeNone)
@@ -2051,7 +2052,7 @@ public:
coordinateB.longitude - currentCoordinate.longitude);
return deltaA < deltaB;
});
-
+
NSUInteger annotationIndex = MGLAnnotationTagNotFound;
if (index >= 0 && (NSUInteger)(index - 2) < visibleAnnotations.size())
{
@@ -2062,20 +2063,20 @@ public:
NSAssert(_annotationContextsByAnnotationTag.count(annotationTag), @"Missing annotation for tag %u.", annotationTag);
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
id <MGLAnnotation> annotation = annotationContext.annotation;
-
+
// Let the annotation view serve as its own accessibility element.
MGLAnnotationView *annotationView = annotationContext.annotationView;
if (annotationView && annotationView.superview)
{
return annotationView;
}
-
+
// Lazily create an accessibility element for the found annotation.
if ( ! annotationContext.accessibilityElement)
{
annotationContext.accessibilityElement = [[MGLAnnotationAccessibilityElement alloc] initWithAccessibilityContainer:self tag:annotationTag];
}
-
+
// Update the accessibility element.
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
CGRect annotationFrame = [self frameOfImage:annotationImage.image centeredAtCoordinate:annotation.coordinate];
@@ -2087,7 +2088,7 @@ public:
CGRect screenRect = UIAccessibilityConvertFrameToScreenCoordinates(annotationFrame, self);
annotationContext.accessibilityElement.accessibilityFrame = screenRect;
annotationContext.accessibilityElement.accessibilityHint = NSLocalizedStringWithDefaultValue(@"ANNOTATION_A11Y_HINT", nil, nil, @"Shows more info", @"Accessibility hint");
-
+
if ([annotation respondsToSelector:@selector(title)])
{
annotationContext.accessibilityElement.accessibilityLabel = annotation.title;
@@ -2096,7 +2097,7 @@ public:
{
annotationContext.accessibilityElement.accessibilityValue = annotation.subtitle;
}
-
+
return annotationContext.accessibilityElement;
}
@@ -2115,9 +2116,9 @@ public:
{
return 1;
}
-
+
std::vector<MGLAnnotationTag> visibleAnnotations = [self annotationTagsInRect:self.bounds];
-
+
MGLAnnotationTag tag = MGLAnnotationTagNotFound;
if ([element isKindOfClass:[MGLAnnotationView class]])
{
@@ -2136,7 +2137,7 @@ public:
{
return NSNotFound;
}
-
+
std::sort(visibleAnnotations.begin(), visibleAnnotations.end());
auto foundElement = std::find(visibleAnnotations.begin(), visibleAnnotations.end(), tag);
if (foundElement == visibleAnnotations.end())
@@ -2176,7 +2177,7 @@ public:
}
_mbglMap->scaleBy(scaleFactor, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y });
[self unrotateIfNeededForGesture];
-
+
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.accessibilityValue);
}
@@ -2226,7 +2227,7 @@ public:
- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate edgePadding:(UIEdgeInsets)insets zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();
-
+
mbgl::CameraOptions cameraOptions;
cameraOptions.center = MGLLatLngFromLocationCoordinate2D(centerCoordinate);
cameraOptions.padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
@@ -2235,7 +2236,7 @@ public:
{
cameraOptions.angle = MGLRadiansFromDegrees(-direction);
}
-
+
mbgl::AnimationOptions animationOptions;
if (duration)
{
@@ -2275,9 +2276,9 @@ public:
{
if (zoomLevel == self.zoomLevel) return;
_mbglMap->cancelTransitions();
-
+
CGFloat duration = animated ? MGLAnimationDuration : 0;
-
+
_mbglMap->setZoom(zoomLevel,
MGLEdgeInsetsFromNSEdgeInsets(self.contentInset),
MGLDurationInSeconds(duration));
@@ -2372,7 +2373,7 @@ public:
- (void)_setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();
-
+
[self willChangeValueForKey:@"visibleCoordinateBounds"];
mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(insets);
padding += MGLEdgeInsetsFromNSEdgeInsets(self.contentInset);
@@ -2382,13 +2383,13 @@ public:
{
latLngs.push_back({coordinates[i].latitude, coordinates[i].longitude});
}
-
+
mbgl::CameraOptions cameraOptions = _mbglMap->cameraForLatLngs(latLngs, padding);
if (direction >= 0)
{
cameraOptions.angle = MGLRadiansFromDegrees(-direction);
}
-
+
mbgl::AnimationOptions animationOptions;
if (duration > 0)
{
@@ -2425,7 +2426,7 @@ public:
{
self.userTrackingMode = MGLUserTrackingModeFollow;
}
-
+
[self _setDirection:direction animated:animated];
}
@@ -2435,7 +2436,7 @@ public:
_mbglMap->cancelTransitions();
CGFloat duration = animated ? MGLAnimationDuration : 0;
-
+
if (self.userTrackingMode == MGLUserTrackingModeNone)
{
_mbglMap->setBearing(direction,
@@ -2510,7 +2511,7 @@ public:
});
};
}
-
+
[self willChangeValueForKey:@"camera"];
_mbglMap->easeTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"camera"];
@@ -2529,7 +2530,7 @@ public:
- (void)flyToCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration peakAltitude:(CLLocationDistance)peakAltitude completionHandler:(nullable void (^)(void))completion
{
self.userTrackingMode = MGLUserTrackingModeNone;
-
+
[self _flyToCamera:camera edgePadding:self.contentInset withDuration:duration peakAltitude:peakAltitude completionHandler:completion];
}
@@ -2562,7 +2563,7 @@ public:
});
};
}
-
+
[self willChangeValueForKey:@"camera"];
_mbglMap->flyTo(cameraOptions, animationOptions);
[self didChangeValueForKey:@"camera"];
@@ -2666,7 +2667,7 @@ public:
bounds.extend([self convertPoint:{ CGRectGetMaxX(rect), CGRectGetMinY(rect) } toLatLngFromView:view]);
bounds.extend([self convertPoint:{ CGRectGetMaxX(rect), CGRectGetMaxY(rect) } toLatLngFromView:view]);
bounds.extend([self convertPoint:{ CGRectGetMinX(rect), CGRectGetMaxY(rect) } toLatLngFromView:view]);
-
+
// The world is wrapping if a point just outside the bounds is also within
// the rect.
mbgl::LatLng outsideLatLng;
@@ -2684,14 +2685,14 @@ public:
bounds.east() + 1,
};
}
-
+
// If the world is wrapping, extend the bounds to cover all longitudes.
if (CGRectContainsPoint(rect, [self convertLatLng:outsideLatLng toPointToView:view]))
{
bounds.extend(mbgl::LatLng(bounds.south(), -180));
bounds.extend(mbgl::LatLng(bounds.south(), 180));
}
-
+
return bounds;
}
@@ -2777,7 +2778,7 @@ public:
{
return nil;
}
-
+
// Map all the annotation tags to the annotations themselves.
std::vector<id <MGLAnnotation>> annotations;
std::transform(_annotationContextsByAnnotationTag.begin(),
@@ -2787,11 +2788,11 @@ public:
{
return pair.second.annotation;
});
-
+
annotations.erase(std::remove_if(annotations.begin(), annotations.end(),
[](const id <MGLAnnotation> annotation) { return annotation == nullptr; }),
annotations.end());
-
+
return [NSArray arrayWithObjects:&annotations[0] count:annotations.size()];
}
@@ -2802,7 +2803,7 @@ public:
{
return nil;
}
-
+
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag[tag];
return annotationContext.annotation;
}
@@ -2814,7 +2815,7 @@ public:
{
return MGLAnnotationTagNotFound;
}
-
+
for (auto &pair : _annotationContextsByAnnotationTag)
{
if (pair.second.annotation == annotation)
@@ -2845,7 +2846,7 @@ public:
BOOL delegateImplementsViewForAnnotation = [self.delegate respondsToSelector:@selector(mapView:viewForAnnotation:)];
BOOL delegateImplementsImageForPoint = [self.delegate respondsToSelector:@selector(mapView:imageForAnnotation:)];
-
+
NSMutableArray *newAnnotationViews = [[NSMutableArray alloc] initWithCapacity:annotations.count];
for (id <MGLAnnotation> annotation in annotations)
@@ -2860,7 +2861,7 @@ public:
{
continue;
}
-
+
// The polyline or polygon knows how to style itself (with the map view’s help).
MGLMultiPoint *multiPoint = (MGLMultiPoint *)annotation;
if (!multiPoint.pointCount) {
@@ -2881,7 +2882,7 @@ public:
MGLAnnotationView *annotationView;
NSString *symbolName;
NSValue *annotationValue = [NSValue valueWithNonretainedObject:annotation];
-
+
if (delegateImplementsViewForAnnotation)
{
annotationView = [self annotationViewForAnnotation:annotation];
@@ -2891,7 +2892,7 @@ public:
annotationView.annotation = annotation;
annotationView.center = [self convertCoordinate:annotation.coordinate toPointToView:self];
[newAnnotationViews addObject:annotationView];
-
+
MGLAnnotationImage *annotationImage = self.invisibleAnnotationImage;
symbolName = annotationImage.styleIconIdentifier;
annotationImagesForAnnotation[annotationValue] = annotationImage;
@@ -2901,10 +2902,10 @@ public:
}
}
}
-
+
if ( ! annotationView) {
MGLAnnotationImage *annotationImage;
-
+
if (delegateImplementsImageForPoint)
{
annotationImage = [self.delegate mapView:self imageForAnnotation:annotation];
@@ -2917,9 +2918,9 @@ public:
{
annotationImage = self.defaultAnnotationImage;
}
-
+
symbolName = annotationImage.styleIconIdentifier;
-
+
if ( ! symbolName)
{
symbolName = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier];
@@ -2929,7 +2930,7 @@ public:
{
[self installAnnotationImage:annotationImage];
}
-
+
annotationImagesForAnnotation[annotationValue] = annotationImage;
}
@@ -2947,7 +2948,7 @@ public:
context.annotationView = annotationView;
context.viewReuseIdentifier = annotationView.reuseIdentifier;
}
-
+
_annotationContextsByAnnotationTag[annotationTag] = context;
if ([annotation isKindOfClass:[NSObject class]]) {
@@ -2958,21 +2959,21 @@ public:
}
[self updateAnnotationContainerViewWithAnnotationViews:newAnnotationViews];
-
+
[self didChangeValueForKey:@"annotations"];
-
+
if ([self.delegate respondsToSelector:@selector(mapView:didAddAnnotationViews:)])
{
[self.delegate mapView:self didAddAnnotationViews:newAnnotationViews];
}
-
+
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
- (void)updateAnnotationContainerViewWithAnnotationViews:(NS_ARRAY_OF(MGLAnnotationView *) *)annotationViews
{
if (annotationViews.count == 0) return;
-
+
MGLAnnotationContainerView *newAnnotationContainerView;
if (self.annotationContainerView)
{
@@ -3008,7 +3009,7 @@ public:
- (MGLAnnotationImage *)invisibleAnnotationImage
{
MGLAnnotationImage *annotationImage = [self dequeueReusableAnnotationImageWithIdentifier:MGLInvisibleStyleMarkerSymbolName];
-
+
if (!annotationImage)
{
UIGraphicsBeginImageContext(CGSizeMake(1, 1));
@@ -3018,27 +3019,27 @@ public:
reuseIdentifier:MGLInvisibleStyleMarkerSymbolName];
annotationImage.styleIconIdentifier = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier];
}
-
+
return annotationImage;
}
- (MGLAnnotationView *)annotationViewForAnnotation:(id<MGLAnnotation>)annotation
{
MGLAnnotationView *annotationView = [self.delegate mapView:self viewForAnnotation:annotation];
-
+
if (annotationView)
{
annotationView.annotation = annotation;
annotationView.mapView = self;
CGRect bounds = UIEdgeInsetsInsetRect({ CGPointZero, annotationView.frame.size }, annotationView.alignmentRectInsets);
-
+
_largestAnnotationViewSize = CGSizeMake(MAX(_largestAnnotationViewSize.width, CGRectGetWidth(bounds)),
MAX(_largestAnnotationViewSize.height, CGRectGetHeight(bounds)));
-
+
_unionedAnnotationRepresentationSize = CGSizeMake(MAX(_unionedAnnotationRepresentationSize.width, _largestAnnotationViewSize.width),
MAX(_unionedAnnotationRepresentationSize.height, _largestAnnotationViewSize.height));
}
-
+
return annotationView;
}
@@ -3046,7 +3047,7 @@ public:
{
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
if (annotationTag == MGLAnnotationTagNotFound) return nil;
-
+
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
return annotationContext.annotationView;
}
@@ -3090,29 +3091,11 @@ public:
NSString *iconIdentifier = annotationImage.styleIconIdentifier;
self.annotationImagesByIdentifier[annotationImage.reuseIdentifier] = annotationImage;
annotationImage.delegate = self;
-
- // retrieve pixels
- CGImageRef image = annotationImage.image.CGImage;
- size_t width = CGImageGetWidth(image);
- size_t height = CGImageGetHeight(image);
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- mbgl::PremultipliedImage cPremultipliedImage(width, height);
- size_t bytesPerPixel = 4;
- size_t bytesPerRow = bytesPerPixel * width;
- size_t bitsPerComponent = 8;
- CGContextRef context = CGBitmapContextCreate(cPremultipliedImage.data.get(), width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
- CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
- CGContextRelease(context);
- CGColorSpaceRelease(colorSpace);
// add sprite
- auto cSpriteImage = std::make_shared<mbgl::SpriteImage>(
- std::move(cPremultipliedImage),
- float(annotationImage.image.scale));
+ std::shared_ptr<mbgl::SpriteImage> sprite(annotationImage.image.mgl_spriteImage);
+ _mbglMap->addAnnotationIcon(iconIdentifier.UTF8String, sprite);
- // sprite upload
- _mbglMap->addAnnotationIcon(iconIdentifier.UTF8String, cSpriteImage);
-
// Create a slop area with a “radius” equal in size to the annotation
// image’s alignment rect, allowing the eventual tap to be on any point
// within this image. Union this slop area with any existing slop areas.
@@ -3158,9 +3141,9 @@ public:
{
[self deselectAnnotation:annotation animated:NO];
}
-
+
_annotationContextsByAnnotationTag.erase(annotationTag);
-
+
if ([annotation isKindOfClass:[NSObject class]] && ![annotation isKindOfClass:[MGLMultiPoint class]])
{
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinate" context:(void *)(NSUInteger)annotationTag];
@@ -3222,7 +3205,7 @@ public:
MGLAnnotationView *reusableView = annotationViewReuseQueue.firstObject;
[reusableView prepareForReuse];
[annotationViewReuseQueue removeObject:reusableView];
-
+
return reusableView;
}
@@ -3249,14 +3232,14 @@ public:
queryRect = CGRectInset(queryRect, -MGLAnnotationImagePaddingForHitTest,
-MGLAnnotationImagePaddingForHitTest);
std::vector<MGLAnnotationTag> nearbyAnnotations = [self annotationTagsInRect:queryRect];
-
+
if (nearbyAnnotations.size())
{
// Assume that the user is fat-fingering an annotation.
CGRect hitRect = CGRectInset({ point, CGSizeZero },
-MGLAnnotationImagePaddingForHitTest,
-MGLAnnotationImagePaddingForHitTest);
-
+
// Filter out any annotation whose image or view is unselectable or for which
// hit testing fails.
auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(),
@@ -3264,10 +3247,10 @@ public:
{
id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag];
NSAssert(annotation, @"Unknown annotation found nearby tap");
-
+
MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag];
CGRect annotationRect;
-
+
MGLAnnotationView *annotationView = annotationContext.annotationView;
if (annotationView)
{
@@ -3275,7 +3258,7 @@ public:
{
return true;
}
-
+
CGPoint calloutAnchorPoint = [self convertCoordinate:annotation.coordinate toPointToView:self];
CGRect frame = CGRectInset({ calloutAnchorPoint, CGSizeZero }, -CGRectGetWidth(annotationView.frame) / 2, -CGRectGetHeight(annotationView.frame) / 2);
annotationRect = UIEdgeInsetsInsetRect(frame, annotationView.alignmentRectInsets);
@@ -3287,28 +3270,28 @@ public:
{
return true;
}
-
+
MGLAnnotationImage *fallbackAnnotationImage = [self dequeueReusableAnnotationImageWithIdentifier:MGLDefaultStyleMarkerSymbolName];
UIImage *fallbackImage = fallbackAnnotationImage.image;
-
+
annotationRect = [self frameOfImage:annotationImage.image ?: fallbackImage centeredAtCoordinate:annotation.coordinate];
}
-
+
// Filter out the annotation if the fattened finger didn’t land
// within the image’s alignment rect.
return !!!CGRectIntersectsRect(annotationRect, hitRect);
});
-
+
nearbyAnnotations.resize(std::distance(nearbyAnnotations.begin(), end));
}
-
+
MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound;
if (nearbyAnnotations.size())
{
// The annotation tags need to be stable in order to compare them with
// the remembered tags.
std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end());
-
+
if (nearbyAnnotations == _annotationsNearbyLastTap)
{
// The first selection in the cycle should be the one nearest to the
@@ -3323,7 +3306,7 @@ public:
coordinateB.longitude - currentCoordinate.longitude);
return deltaA < deltaB;
});
-
+
// The last time we persisted a set of annotations, we had the same
// set of annotations as we do now. Cycle through them.
if (_selectedAnnotationTag == MGLAnnotationTagNotFound
@@ -3361,7 +3344,7 @@ public:
{
_annotationsNearbyLastTap = nearbyAnnotations;
}
-
+
// Choose the first nearby annotation.
if (nearbyAnnotations.size())
{
@@ -3369,7 +3352,7 @@ public:
}
}
}
-
+
return hitAnnotationTag;
}
@@ -3441,7 +3424,7 @@ public:
}
[self deselectAnnotation:self.selectedAnnotation animated:NO];
-
+
// Add the annotation to the map if it hasn’t been added yet.
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
if (annotationTag == MGLAnnotationTagNotFound && annotation != self.userLocation)
@@ -3450,29 +3433,29 @@ public:
annotationTag = [self annotationTagForAnnotation:annotation];
if (annotationTag == MGLAnnotationTagNotFound) return;
}
-
+
// By default attempt to use the GL annotation image frame as the positioning rect.
CGRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag];
-
+
MGLAnnotationView *annotationView = nil;
-
+
if (annotation != self.userLocation)
{
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
-
+
annotationView = annotationContext.annotationView;
-
+
if (annotationView && annotationView.enabled)
{
// Annotations represented by views use the view frame as the positioning rect.
positioningRect = annotationView.frame;
-
+
[annotationView.superview bringSubviewToFront:annotationView];
[annotationView setSelected:YES animated:animated];
}
}
-
+
// The client can request that any annotation be selected (even ones that are offscreen).
// The annotation can’t be selected if no part of it is hittable.
if ( ! CGRectIntersectsRect(positioningRect, self.bounds) && annotation != self.userLocation)
@@ -3502,7 +3485,7 @@ public:
if (_userLocationAnnotationIsSelected)
{
positioningRect = [self.userLocationAnnotationView.layer.presentationLayer frame];
-
+
CGRect implicitAnnotationFrame = [self.userLocationAnnotationView.layer.presentationLayer frame];
CGRect explicitAnnotationFrame = self.userLocationAnnotationView.frame;
_initialImplicitCalloutViewOffset = CGPointMake(CGRectGetMinX(explicitAnnotationFrame) - CGRectGetMinX(implicitAnnotationFrame),
@@ -3551,7 +3534,7 @@ public:
{
[self.delegate mapView:self didSelectAnnotation:annotation];
}
-
+
if (annotationView && [self.delegate respondsToSelector:@selector(mapView:didSelectAnnotationView:)])
{
[self.delegate mapView:self didSelectAnnotationView:annotationView];
@@ -3573,7 +3556,7 @@ public:
- (CGRect)positioningRectForCalloutForAnnotationWithTag:(MGLAnnotationTag)annotationTag
{
MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag];
-
+
id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag];
if ( ! annotation)
{
@@ -3588,10 +3571,10 @@ public:
{
return CGRectZero;
}
-
+
CGRect positioningRect = [self frameOfImage:image centeredAtCoordinate:annotation.coordinate];
positioningRect.origin.x -= 0.5;
-
+
return CGRectInset(positioningRect, -MGLAnnotationImagePaddingForCallout,
-MGLAnnotationImagePaddingForCallout);
}
@@ -3613,10 +3596,10 @@ public:
{
return nil;
}
-
+
NSString *customSymbol = _annotationContextsByAnnotationTag.at(annotationTag).imageReuseIdentifier;
NSString *symbolName = customSymbol.length ? customSymbol : MGLDefaultStyleMarkerSymbolName;
-
+
return [self dequeueReusableAnnotationImageWithIdentifier:symbolName];
}
@@ -3628,11 +3611,11 @@ public:
{
// dismiss popup
[self.calloutViewForSelectedAnnotation dismissCalloutAnimated:animated];
-
+
// deselect annotation view
MGLAnnotationView *annotationView = nil;
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
-
+
if (annotationTag != MGLAnnotationTagNotFound)
{
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
@@ -3649,7 +3632,7 @@ public:
{
[self.delegate mapView:self didDeselectAnnotation:annotation];
}
-
+
if (annotationView && [self.delegate respondsToSelector:@selector(mapView:didDeselectAnnotationView:)])
{
[self.delegate mapView:self didDeselectAnnotationView:annotationView];
@@ -3664,7 +3647,7 @@ public:
{
return;
}
-
+
// The user location callout view initially points to the user location
// annotation’s implicit (visual) frame, which is offset from the
// annotation’s explicit frame. Now the callout view needs to rendezvous
@@ -3728,19 +3711,19 @@ public:
NSString *iconIdentifier = annotationImage.styleIconIdentifier;
NSString *fallbackReuseIdentifier = MGLDefaultStyleMarkerSymbolName;
NSString *fallbackIconIdentifier = [MGLAnnotationSpritePrefix stringByAppendingString:fallbackReuseIdentifier];
-
+
// Remove the old icon from the style.
if ( ! [iconIdentifier isEqualToString:fallbackIconIdentifier]) {
_mbglMap->removeAnnotationIcon(iconIdentifier.UTF8String);
}
-
+
if (annotationImage.image)
{
// Add the new icon to the style.
NSString *updatedIconIdentifier = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier];
annotationImage.styleIconIdentifier = updatedIconIdentifier;
[self installAnnotationImage:annotationImage];
-
+
if ([iconIdentifier isEqualToString:fallbackIconIdentifier])
{
// Update any annotations associated with the annotation image.
@@ -3755,7 +3738,7 @@ public:
{
[self installAnnotationImage:self.defaultAnnotationImage];
}
-
+
// Update any annotations associated with the annotation image.
[self applyIconIdentifier:fallbackIconIdentifier toAnnotationsWithImageReuseIdentifier:reuseIdentifier];
}
@@ -3834,11 +3817,11 @@ public:
{
[self.delegate mapViewWillStartLocatingUser:self];
}
-
+
self.userLocation = [[MGLUserLocation alloc] initWithMapView:self];
-
+
MGLUserLocationAnnotationView *userLocationAnnotationView;
-
+
if ([self.delegate respondsToSelector:@selector(mapView:viewForAnnotation:)])
{
userLocationAnnotationView = (MGLUserLocationAnnotationView *)[self.delegate mapView:self viewForAnnotation:self.userLocation];
@@ -3852,11 +3835,11 @@ public:
userLocationAnnotationView = nil;
}
}
-
+
self.userLocationAnnotationView = userLocationAnnotationView ?: [[MGLFaux3DUserLocationAnnotationView alloc] init];
self.userLocationAnnotationView.mapView = self;
self.userLocationAnnotationView.userLocation = self.userLocation;
-
+
self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
@@ -3934,7 +3917,7 @@ public:
case MGLUserTrackingModeNone:
{
self.userTrackingState = MGLUserTrackingStatePossible;
-
+
[self.locationManager stopUpdatingHeading];
// Immediately update the annotation view; other cases update inside
@@ -3965,7 +3948,7 @@ public:
{
self.userTrackingState = animated ? MGLUserTrackingStatePossible : MGLUserTrackingStateChanged;
}
-
+
self.showsUserLocation = YES;
if (self.zoomLevel < self.currentMinimumZoom)
@@ -4066,7 +4049,7 @@ public:
duration = MIN([newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp], MGLUserLocationAnimationDuration);
}
[self updateUserLocationAnnotationViewAnimatedWithDuration:duration];
-
+
if (self.userTrackingMode == MGLUserTrackingModeNone &&
self.userLocationAnnotationView.accessibilityElementIsFocused &&
[UIApplication sharedApplication].applicationState == UIApplicationStateActive)
@@ -4084,7 +4067,7 @@ public:
{
return;
}
-
+
// If the user location annotation is already where it’s supposed to be,
// don’t change the viewport.
CGPoint correctPoint = self.userLocationAnnotationViewCenter;
@@ -4094,7 +4077,7 @@ public:
{
return;
}
-
+
if (self.userTrackingMode == MGLUserTrackingModeFollowWithCourse
&& CLLocationCoordinate2DIsValid(self.targetCoordinate))
{
@@ -4135,7 +4118,7 @@ public:
- (void)didUpdateLocationSignificantlyAnimated:(BOOL)animated
{
self.userTrackingState = MGLUserTrackingStateBegan;
-
+
MGLMapCamera *camera = self.camera;
camera.centerCoordinate = self.userLocation.location.coordinate;
camera.heading = self.directionByFollowingWithCourse;
@@ -4146,7 +4129,7 @@ public:
camera.centerCoordinate.latitude,
self.frame.size);
}
-
+
__weak MGLMapView *weakSelf = self;
[self _flyToCamera:camera
edgePadding:self.edgePaddingForFollowing
@@ -4179,7 +4162,7 @@ public:
}
};
}
-
+
CLLocationCoordinate2D foci[] = {
self.userLocation.location.coordinate,
self.targetCoordinate,
@@ -4203,7 +4186,7 @@ public:
{
// Center on user location unless we're already centered there (or very close).
CGPoint correctPoint = self.userLocationAnnotationViewCenter;
-
+
// Shift the entire frame upward or downward to accommodate a shifted user
// location annotation view.
CGRect bounds = self.bounds;
@@ -4245,7 +4228,7 @@ public:
{
direction = self.userLocation.location.course;
}
-
+
if (direction >= 0)
{
if (self.userLocationVerticalAlignment == MGLAnnotationVerticalAlignmentTop)
@@ -4345,7 +4328,7 @@ public:
- (NS_ARRAY_OF(id <MGLFeature>) *)visibleFeaturesAtPoint:(CGPoint)point inStyleLayersWithIdentifiers:(NS_SET_OF(NSString *) *)styleLayerIdentifiers
{
mbgl::ScreenCoordinate screenCoordinate = { point.x, point.y };
-
+
mbgl::optional<std::vector<std::string>> optionalLayerIDs;
if (styleLayerIdentifiers)
{
@@ -4357,7 +4340,7 @@ public:
}];
optionalLayerIDs = layerIDs;
}
-
+
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenCoordinate, optionalLayerIDs);
return MGLFeaturesFromMBGLFeatures(features);
}
@@ -4371,7 +4354,7 @@ public:
{ CGRectGetMinX(rect), CGRectGetMinY(rect) },
{ CGRectGetMaxX(rect), CGRectGetMaxY(rect) },
};
-
+
mbgl::optional<std::vector<std::string>> optionalLayerIDs;
if (styleLayerIdentifiers) {
__block std::vector<std::string> layerIDs;
@@ -4381,7 +4364,7 @@ public:
}];
optionalLayerIDs = layerIDs;
}
-
+
std::vector<mbgl::Feature> features = _mbglMap->queryRenderedFeatures(screenBox, optionalLayerIDs);
return MGLFeaturesFromMBGLFeatures(features);
}
@@ -4412,7 +4395,7 @@ public:
&& state != UIGestureRecognizerStateChanged)
{
[self unrotateIfNeededAnimated:YES];
-
+
// Snap to north.
if ((self.direction < MGLToleranceForSnappingToNorth
|| self.direction > 360 - MGLToleranceForSnappingToNorth)
@@ -4585,21 +4568,21 @@ public:
- (void)updateAnnotationViews
{
BOOL delegateImplementsViewForAnnotation = [self.delegate respondsToSelector:@selector(mapView:viewForAnnotation:)];
-
+
if (!delegateImplementsViewForAnnotation)
{
return;
}
-
+
[CATransaction begin];
[CATransaction setDisableActions:YES];
-
+
for (auto &pair : _annotationContextsByAnnotationTag)
{
CGRect viewPort = CGRectInset(self.bounds,
-_largestAnnotationViewSize.width / 2.0 - MGLAnnotationUpdateViewportOutset.width / 2.0,
-_largestAnnotationViewSize.height / 2.0 - MGLAnnotationUpdateViewportOutset.width);
-
+
MGLAnnotationContext &annotationContext = pair.second;
MGLAnnotationView *annotationView = annotationContext.annotationView;
@@ -4617,7 +4600,7 @@ public:
annotationView.mapView = self;
annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
annotationContext.annotationView = annotationView;
-
+
if (!annotationView.superview) {
[self.annotationContainerView insertSubview:annotationView atIndex:0];
}
@@ -4628,7 +4611,7 @@ public:
continue;
}
}
-
+
bool annotationViewIsVisible = CGRectContainsRect(viewPort, annotationView.frame);
if (!annotationViewIsVisible && annotationContext.viewReuseIdentifier)
{
@@ -4639,18 +4622,18 @@ public:
annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
}
}
-
+
[CATransaction commit];
}
- (void)enqueueAnnotationViewForAnnotationContext:(MGLAnnotationContext &)annotationContext
{
MGLAnnotationView *annotationView = annotationContext.annotationView;
-
+
if (!annotationView) return;
-
+
annotationView.annotation = nil;
-
+
if (annotationContext.viewReuseIdentifier)
{
NSMutableArray *annotationViewReuseQueue = [self annotationViewReuseQueueForIdentifier:annotationContext.viewReuseIdentifier];
@@ -4680,7 +4663,7 @@ public:
{
userPoint = [self convertCoordinate:self.userLocation.coordinate toPointToView:self];
}
-
+
if ( ! annotationView.superview)
{
[self.glView addSubview:annotationView];
@@ -4709,10 +4692,10 @@ public:
annotationView.center = userPoint;
} completion:NULL];
_userLocationAnimationCompletionDate = [NSDate dateWithTimeIntervalSinceNow:duration];
-
+
annotationView.hidden = NO;
[annotationView update];
-
+
if (_userLocationAnnotationIsSelected)
{
// Ensure the callout view still points to its annotation.
@@ -4731,7 +4714,7 @@ public:
// User has moved far enough outside of the viewport that showing it or
// its callout would be useless.
annotationView.hidden = YES;
-
+
if (_userLocationAnnotationIsSelected)
{
[self deselectAnnotation:self.selectedAnnotation animated:YES];
@@ -4749,7 +4732,7 @@ public:
contentFrame = self.contentFrame;
}
CGPoint center = CGPointMake(CGRectGetMidX(contentFrame), CGRectGetMidY(contentFrame));
-
+
// When tracking course, it’s more important to see the road ahead, so
// weight the user dot down towards the bottom.
switch (self.userLocationVerticalAlignment) {
@@ -4762,7 +4745,7 @@ public:
center.y = CGRectGetMaxY(contentFrame);
break;
}
-
+
return center;
}
@@ -4771,7 +4754,7 @@ public:
CLLocationDirection direction = self.direction;
CLLocationDirection plateDirection = mbgl::util::wrap(-direction, 0., 360.);
self.compassView.transform = CGAffineTransformMakeRotation(MGLRadiansFromDegrees(plateDirection));
-
+
self.compassView.isAccessibilityElement = direction > 0;
self.compassView.accessibilityValue = [_accessibilityCompassFormatter stringFromDirection:direction];
@@ -4811,7 +4794,7 @@ public:
[NSException raise:@"Resource not found" format:
@"The resource named “%@” could not be found in the Mapbox framework bundle.", imageName];
}
-
+
return [UIImage imageWithContentsOfFile:path];
}
@@ -4928,7 +4911,7 @@ public:
{
_annotationViewReuseQueueByIdentifier[identifier] = [NSMutableArray array];
}
-
+
return _annotationViewReuseQueueByIdentifier[identifier];
}
@@ -5130,7 +5113,7 @@ public:
MGLCustomStyleLayerDrawingHandler d,
MGLCustomStyleLayerCompletionHandler f)
: prepare(p), draw(d), finish(f) {}
-
+
MGLCustomStyleLayerPreparationHandler prepare;
MGLCustomStyleLayerDrawingHandler draw;
MGLCustomStyleLayerCompletionHandler finish;
diff --git a/platform/ios/src/UIImage+MGLAdditions.h b/platform/ios/src/UIImage+MGLAdditions.h
new file mode 100644
index 0000000000..411220c503
--- /dev/null
+++ b/platform/ios/src/UIImage+MGLAdditions.h
@@ -0,0 +1,9 @@
+#import <UIKit/UIKit.h>
+
+#include <mbgl/sprite/sprite_image.hpp>
+
+@interface UIImage (MGLAdditions)
+
+- (std::unique_ptr<mbgl::SpriteImage>)mgl_spriteImage;
+
+@end
diff --git a/platform/ios/src/UIImage+MGLAdditions.mm b/platform/ios/src/UIImage+MGLAdditions.mm
new file mode 100644
index 0000000000..8ec8f9e15f
--- /dev/null
+++ b/platform/ios/src/UIImage+MGLAdditions.mm
@@ -0,0 +1,27 @@
+#import "UIImage+MGLAdditions.h"
+
+@implementation UIImage (MGLAdditions)
+
+- (std::unique_ptr<mbgl::SpriteImage>)mgl_spriteImage
+{
+ CGImageRef cgImage = self.CGImage;
+ size_t width = CGImageGetWidth(cgImage);
+ size_t height = CGImageGetHeight(cgImage);
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ mbgl::PremultipliedImage cPremultipliedImage(width, height);
+ size_t bytesPerPixel = 4;
+ size_t bytesPerRow = bytesPerPixel * width;
+ size_t bitsPerComponent = 8;
+
+ CGContextRef context = CGBitmapContextCreate(cPremultipliedImage.data.get(),
+ width, height, bitsPerComponent, bytesPerRow,
+ colorSpace, kCGImageAlphaPremultipliedLast);
+
+ CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);
+ CGContextRelease(context);
+ CGColorSpaceRelease(colorSpace);
+
+ return std::make_unique<mbgl::SpriteImage>(std::move(cPremultipliedImage), float(self.scale));
+}
+
+@end