Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[ios] Avoid drawing view annotations across pixel boundaries #10219

Merged
merged 3 commits into from
Oct 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions platform/darwin/src/MGLGeometry.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#import <mbgl/util/projection.hpp>

#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import <Cocoa/Cocoa.h>
#endif

/** Vertical field of view, measured in degrees, for determining the altitude
of the viewpoint.

Expand Down Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions platform/darwin/src/MGLGeometry_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,5 @@ NS_INLINE MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGL
cos(distance) - sin(coordinate.latitude) * sin(otherLatitude));
return MGLRadianCoordinate2DMake(otherLatitude, otherLongitude);
}

CGPoint MGLPointRounded(CGPoint point);
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 12 additions & 6 deletions platform/ios/src/MGLFaux3DUserLocationAnnotationView.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -175,12 +175,16 @@ - (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;

_puckArrow.lineJoin = @"round";
_puckArrow.lineWidth = 1.f;
_puckArrow.strokeColor = _puckArrow.fillColor;

[self.layer addSublayer:_puckArrow];
}
if (self.userLocation.location.course >= 0)
Expand Down Expand Up @@ -302,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;
Expand Down Expand Up @@ -431,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;
Expand All @@ -456,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
11 changes: 5 additions & 6 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3379,7 +3379,7 @@ - (void)addAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -4582,7 +4582,6 @@ - (void)setShowsUserHeadingIndicator:(BOOL)showsUserHeadingIndicator
if (_showsUserHeadingIndicator)
{
self.showsUserLocation = YES;

}
[self validateUserHeadingUpdating];
}
Expand Down Expand Up @@ -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]);
}
}

Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions platform/ios/src/MGLScaleBar.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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));
Expand Down