From 6523b16c61d988960e24713d0198685801147c45 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Tue, 3 Oct 2017 15:38:08 -0700 Subject: [PATCH 1/3] [ios] Slightly round the corners of the puck arrow --- platform/ios/src/MGLFaux3DUserLocationAnnotationView.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m b/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m index 21f6aaa5406..63e754d9c6d 100644 --- a/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m +++ b/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m @@ -10,7 +10,7 @@ const CGFloat MGLUserLocationAnnotationHaloSize = 115.0; const CGFloat MGLUserLocationAnnotationPuckSize = 45.0; -const CGFloat MGLUserLocationAnnotationArrowSize = MGLUserLocationAnnotationPuckSize * 0.6; +const CGFloat MGLUserLocationAnnotationArrowSize = MGLUserLocationAnnotationPuckSize * 0.5; const CGFloat MGLUserLocationHeadingUpdateThreshold = 0.01; @@ -181,6 +181,10 @@ - (void)drawPuck _puckArrow.rasterizationScale = [UIScreen mainScreen].scale; _puckArrow.drawsAsynchronously = YES; + _puckArrow.lineJoin = @"round"; + _puckArrow.lineWidth = 1.f; + _puckArrow.strokeColor = _puckArrow.fillColor; + [self.layer addSublayer:_puckArrow]; } if (self.userLocation.location.course >= 0) From cabf5d2970148d47b9b1ecba02bfa1f36e1f94ac Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Tue, 3 Oct 2017 18:08:13 -0700 Subject: [PATCH 2/3] [ios] Avoid drawing view annotations across pixel boundaries --- platform/darwin/src/MGLGeometry.mm | 13 +++++++++++++ platform/darwin/src/MGLGeometry_Private.h | 2 ++ platform/ios/CHANGELOG.md | 1 + .../ios/src/MGLFaux3DUserLocationAnnotationView.m | 12 +++++++----- platform/ios/src/MGLMapView.mm | 11 +++++------ 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm index 1540a3a7419..43bf74c4072 100644 --- a/platform/darwin/src/MGLGeometry.mm +++ b/platform/darwin/src/MGLGeometry.mm @@ -4,6 +4,10 @@ #import +#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +#import +#endif + /** Vertical field of view, measured in degrees, for determining the altitude of the viewpoint. @@ -57,3 +61,12 @@ CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLo CGFloat mapPixelWidthAtZoom = std::cos(MGLRadiansFromDegrees(latitude)) * mbgl::util::M2PI * mbgl::util::EARTH_RADIUS_M / metersPerPixel; return ::log2(mapPixelWidthAtZoom / mbgl::util::tileSize); } + +CGPoint MGLPointRounded(CGPoint point) { +#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR + CGFloat scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [UIScreen mainScreen].nativeScale : [UIScreen mainScreen].scale; +#elif TARGET_OS_MAC + CGFloat scaleFactor = [NSScreen mainScreen].backingScaleFactor; +#endif + return CGPointMake(round(point.x * scaleFactor) / scaleFactor, round(point.y * scaleFactor) / scaleFactor); +} diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h index 88fcf5b5762..87a19989c12 100644 --- a/platform/darwin/src/MGLGeometry_Private.h +++ b/platform/darwin/src/MGLGeometry_Private.h @@ -138,3 +138,5 @@ NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGL cos(distance) - sin(coordinate.latitude) * sin(otherLatitude)); return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude); } + +CGPoint MGLPointRounded(CGPoint point); diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 3dd46f3e932..eca338db138 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -31,6 +31,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Selecting an annotation no longer sets the user tracking mode to `MGLUserTrackingModeNone`. ([#10094](https://github.com/mapbox/mapbox-gl-native/pull/10094)) * Added `-[MGLMapView cameraThatFitsShape:direction:edgePadding:]` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)) * Added support selection of shape and polyline annotations.([#9984](https://github.com/mapbox/mapbox-gl-native/pull/9984)) +* Fixed an issue where view annotations could be slightly misaligned. View annotation placement is now rounded to the nearest pixel. ([#10219](https://github.com/mapbox/mapbox-gl-native/pull/10219)) ### Other changes diff --git a/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m b/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m index 63e754d9c6d..1ed3d86ad10 100644 --- a/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m +++ b/platform/ios/src/MGLFaux3DUserLocationAnnotationView.m @@ -175,8 +175,8 @@ - (void)drawPuck _puckArrow = [CAShapeLayer layer]; _puckArrow.path = [[self puckArrow] CGPath]; _puckArrow.fillColor = [self.mapView.tintColor CGColor]; - _puckArrow.bounds = CGRectMake(0, 0, MGLUserLocationAnnotationArrowSize, MGLUserLocationAnnotationArrowSize); - _puckArrow.position = CGPointMake(super.bounds.size.width / 2.0, super.bounds.size.height / 2.0); + _puckArrow.bounds = CGRectMake(0, 0, round(MGLUserLocationAnnotationArrowSize), round(MGLUserLocationAnnotationArrowSize)); + _puckArrow.position = CGPointMake(CGRectGetMidX(super.bounds), CGRectGetMidY(super.bounds)); _puckArrow.shouldRasterize = YES; _puckArrow.rasterizationScale = [UIScreen mainScreen].scale; _puckArrow.drawsAsynchronously = YES; @@ -306,7 +306,7 @@ - (void)drawDot [CATransaction setDisableActions:shouldDisableActions]; _accuracyRingLayer.bounds = CGRectMake(0, 0, accuracyRingSize, accuracyRingSize); - _accuracyRingLayer.cornerRadius = accuracyRingSize / 2; + _accuracyRingLayer.cornerRadius = accuracyRingSize / 2.0; // match the halo to the accuracy ring _haloLayer.bounds = _accuracyRingLayer.bounds; @@ -435,9 +435,11 @@ - (void)drawDot - (CALayer *)circleLayerWithSize:(CGFloat)layerSize { + layerSize = round(layerSize); + CALayer *circleLayer = [CALayer layer]; circleLayer.bounds = CGRectMake(0, 0, layerSize, layerSize); - circleLayer.position = CGPointMake(super.bounds.size.width / 2.0, super.bounds.size.height / 2.0); + circleLayer.position = CGPointMake(CGRectGetMidX(super.bounds), CGRectGetMidY(super.bounds)); circleLayer.cornerRadius = layerSize / 2.0; circleLayer.shouldRasterize = YES; circleLayer.rasterizationScale = [UIScreen mainScreen].scale; @@ -460,7 +462,7 @@ - (CAAnimationGroup *)loopingAnimationGroupWithDuration:(CGFloat)animationDurati - (CGFloat)calculateAccuracyRingSize { // diameter in screen points - return self.userLocation.location.horizontalAccuracy / [self.mapView metersPerPointAtLatitude:self.userLocation.coordinate.latitude] * 2.0; + return round(self.userLocation.location.horizontalAccuracy / [self.mapView metersPerPointAtLatitude:self.userLocation.coordinate.latitude] * 2.0); } @end diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 4112df6e76c..d0d34dbfa90 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -3379,7 +3379,7 @@ - (void)addAnnotations:(NS_ARRAY_OF(id ) *)annotations { annotationViewsForAnnotation[annotationValue] = annotationView; annotationView.annotation = annotation; - annotationView.center = [self convertCoordinate:annotation.coordinate toPointToView:self]; + annotationView.center = MGLPointRounded([self convertCoordinate:annotation.coordinate toPointToView:self]); [newAnnotationViews addObject:annotationView]; MGLAnnotationImage *annotationImage = self.invisibleAnnotationImage; @@ -3805,7 +3805,7 @@ - (MGLAnnotationTag)annotationTagAtPoint:(CGPoint)point persistingResults:(BOOL) return true; } - CGPoint calloutAnchorPoint = [self convertCoordinate:annotation.coordinate toPointToView:self]; + CGPoint calloutAnchorPoint = MGLPointRounded([self convertCoordinate:annotation.coordinate toPointToView:self]); CGRect frame = CGRectInset({ calloutAnchorPoint, CGSizeZero }, -CGRectGetWidth(annotationView.frame) / 2, -CGRectGetHeight(annotationView.frame) / 2); annotationRect = UIEdgeInsetsInsetRect(frame, annotationView.alignmentRectInsets); } @@ -4143,7 +4143,7 @@ - (CGRect)positioningRectForCalloutForAnnotationWithTag:(MGLAnnotationTag)annota /// image centered at the given coordinate. - (CGRect)frameOfImage:(UIImage *)image centeredAtCoordinate:(CLLocationCoordinate2D)coordinate { - CGPoint calloutAnchorPoint = [self convertCoordinate:coordinate toPointToView:self]; + CGPoint calloutAnchorPoint = MGLPointRounded([self convertCoordinate:coordinate toPointToView:self]); CGRect frame = CGRectInset({ calloutAnchorPoint, CGSizeZero }, -image.size.width / 2, -image.size.height / 2); return UIEdgeInsetsInsetRect(frame, image.alignmentRectInsets); } @@ -4582,7 +4582,6 @@ - (void)setShowsUserHeadingIndicator:(BOOL)showsUserHeadingIndicator if (_showsUserHeadingIndicator) { self.showsUserLocation = YES; - } [self validateUserHeadingUpdating]; } @@ -5288,7 +5287,7 @@ - (void)updateAnnotationViews if (annotationView) { - annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]; + annotationView.center = MGLPointRounded([self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self]); } } @@ -5406,7 +5405,7 @@ - (void)updateUserLocationAnnotationViewAnimatedWithDuration:(NSTimeInterval)dur } else { - userPoint = [self convertCoordinate:self.userLocation.coordinate toPointToView:self]; + userPoint = MGLPointRounded([self convertCoordinate:self.userLocation.coordinate toPointToView:self]); } if ( ! annotationView.superview) From 817e5c109f5e48e0ce05b05058498cfa6be8e2da Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Tue, 17 Oct 2017 20:56:22 -0400 Subject: [PATCH 3/3] [ios] Fix scale bar label alignment --- platform/ios/src/MGLScaleBar.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/ios/src/MGLScaleBar.mm b/platform/ios/src/MGLScaleBar.mm index 410aa7d57e5..f63c39009fc 100644 --- a/platform/ios/src/MGLScaleBar.mm +++ b/platform/ios/src/MGLScaleBar.mm @@ -334,7 +334,7 @@ - (void)updateLabels { } - (void)layoutBars { - CGFloat barWidth = (CGRectGetWidth(self.bounds) - self.borderWidth * 2.0f) / self.bars.count; + CGFloat barWidth = round((CGRectGetWidth(self.bounds) - self.borderWidth * 2.0f) / self.bars.count); NSUInteger i = 0; for (UIView *bar in self.bars) { @@ -357,11 +357,11 @@ - (void)layoutBars { } - (void)layoutLabels { - CGFloat barWidth = self.bounds.size.width / self.bars.count; + CGFloat barWidth = round(self.bounds.size.width / self.bars.count); BOOL RTL = [self usesRightToLeftLayout]; NSUInteger i = RTL ? self.bars.count : 0; for (MGLScaleBarLabel *label in self.labels) { - CGFloat xPosition = barWidth * i - CGRectGetMidX(label.bounds) + self.borderWidth; + CGFloat xPosition = round(barWidth * i - CGRectGetMidX(label.bounds) + self.borderWidth); label.frame = CGRectMake(xPosition, 0, CGRectGetWidth(label.bounds), CGRectGetHeight(label.bounds));