From b8388168dd130c67c77254565cdb576df7905915 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Wed, 1 Jul 2015 10:42:38 -0400 Subject: [PATCH 01/41] split renderSync and transition nudging to allow client view syncing --- include/mbgl/map/map.hpp | 5 ++++- platform/ios/MGLMapView.mm | 3 ++- src/mbgl/map/map.cpp | 8 ++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 8178fab49..72800a9c1 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -64,7 +64,10 @@ public: void renderStill(StillImageCallback callback); // Triggers a synchronous or asynchronous render. - void renderSync(); + bool renderSync(); + + // Nudges transitions one step, possibly notifying of the need for a rerender. + void nudgeTransitions(bool forceRerender); // Notifies the Map thread that the state has changed and an update might be necessary. void update(Update update = Update::Nothing); diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 6f6a6d9ae..01a716ad9 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -687,7 +687,8 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) _mbglMap->setSourceTileCacheSize(cacheSize); - _mbglMap->renderSync(); + bool needsRerender = _mbglMap->renderSync(); + _mbglMap->nudgeTransitions(needsRerender); } } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 37cd3be33..449d77fbe 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -48,7 +48,7 @@ void Map::renderStill(StillImageCallback callback) { FrameData{ view.getFramebufferSize() }, callback); } -void Map::renderSync() { +bool Map::renderSync() { if (renderState == RenderState::never) { view.notifyMapChange(MapChangeWillStartRenderingMap); } @@ -69,9 +69,13 @@ void Map::renderSync() { view.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered); } + return result.needsRerender; +} + +void Map::nudgeTransitions(bool forceRerender) { if (transform->needsTransition()) { update(Update(transform->updateTransitions(Clock::now()))); - } else if (result.needsRerender) { + } else if (forceRerender) { update(); } } From a67e80219f90c409dfce8bfef91d9131dabd8d4f Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Wed, 8 Jul 2015 12:21:40 -0700 Subject: [PATCH 02/41] refs #1125, 1813: update user dot tracking in one place Now that we have cleanup around the map viewport change notifications, this only needs to happen in one place: the GL frame draw loop. --- platform/ios/MGLMapView.mm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 01a716ad9..f527a9a2e 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -688,6 +688,9 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) _mbglMap->setSourceTileCacheSize(cacheSize); bool needsRerender = _mbglMap->renderSync(); + + [self updateUserLocationAnnotationView]; + _mbglMap->nudgeTransitions(needsRerender); } } @@ -2352,8 +2355,6 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) self.userLocationAnnotationView.haloLayer.hidden = ! CLLocationCoordinate2DIsValid(self.userLocation.coordinate) || newLocation.horizontalAccuracy > 10; - - [self updateUserLocationAnnotationView]; } - (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager @@ -2510,8 +2511,6 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) case mbgl::MapChangeRegionWillChange: case mbgl::MapChangeRegionWillChangeAnimated: { - [self updateUserLocationAnnotationView]; - [self deselectAnnotation:self.selectedAnnotation animated:NO]; BOOL animated = (change == mbgl::MapChangeRegionWillChangeAnimated); @@ -2546,7 +2545,6 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) } case mbgl::MapChangeRegionIsChanging: { - [self updateUserLocationAnnotationView]; [self updateCompass]; if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)]) @@ -2558,7 +2556,6 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng) case mbgl::MapChangeRegionDidChange: case mbgl::MapChangeRegionDidChangeAnimated: { - [self updateUserLocationAnnotationView]; [self updateCompass]; if (self.pan.state == UIGestureRecognizerStateChanged || From 49fe6df0dbcfb70222b10b72be681b68526e7891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 8 Jul 2015 12:41:34 -0700 Subject: [PATCH 03/41] Assert if -mapView:symbolNameForAnnotation: is implemented Fixes #1851. --- platform/ios/MGLMapView.mm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index f527a9a2e..3fd0ed02c 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -455,6 +455,14 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) if (_delegate == delegate) return; _delegate = delegate; + + if ([delegate respondsToSelector:@selector(mapView:symbolNameForAnnotation:)]) + { + [NSException raise:@"Method unavailable" format: + @"-mapView:symbolNameForAnnotation: has been removed from the MGLMapViewDelegate protocol, but %@ still implements it. " + @"Implement -[%@ mapView:imageForAnnotation:] instead.", + NSStringFromClass([delegate class]), NSStringFromClass([delegate class])]; + } } #pragma mark - Layout - From 184afb01adf4553c5c91d761b0d667eaafe646c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 8 Jul 2015 13:13:32 -0700 Subject: [PATCH 04/41] Removed documentation for unavailable method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So it doesn’t show up in the generated docset. --- include/mbgl/ios/MGLMapView.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h index 900728034..4b21d5bad 100644 --- a/include/mbgl/ios/MGLMapView.h +++ b/include/mbgl/ios/MGLMapView.h @@ -345,10 +345,6 @@ IB_DESIGNABLE /** @name Managing the Display of Annotations */ -/** Returns the style's symbol name to use for the marker for the specified point annotation object. -* @param mapView The map view that requested the annotation symbol name. -* @param annotation The object representing the annotation that is about to be displayed. -* @return The marker symbol to display for the specified annotation or `nil` if you want to display the default symbol. */ - (nullable NSString *)mapView:(MGLMapView *)mapView symbolNameForAnnotation:(id )annotation __attribute__((unavailable("Use -mapView:imageForAnnotation:."))); /** Returns an image object to use for the marker for the specified point annotation object. From 0fd9fe78dbb27cdd8cdea1d664596c226a6273b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 1 Jul 2015 23:48:16 -0700 Subject: [PATCH 05/41] Defer initialization until app enters foreground Defer the creation of EAGLEContext and GLKView and the loading of OpenGL ES extensions. It is GLKView that drives the background crash, and Apple documentation specifically warns not to initialize an EAGLContext in the background. All the while, it should be safe for client code to avail itself of any public methods on MGLMapView. Fixes #1460. --- platform/ios/MGLMapView.mm | 105 ++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 41 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 3fd0ed02c..6220c8971 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -206,58 +206,28 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) - (void)commonInit { _isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent; + + BOOL background = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; + if (!background) + { + [self createGLView]; + } - // create context - // - _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - NSAssert(_context, @"Failed to create OpenGL ES context."); - // setup accessibility - // self.accessibilityLabel = @"Map"; - - // create GL view - // - _glView = [[GLKView alloc] initWithFrame:self.bounds context:_context]; - _glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _glView.enableSetNeedsDisplay = YES; - _glView.drawableStencilFormat = GLKViewDrawableStencilFormat8; - _glView.drawableDepthFormat = GLKViewDrawableDepthFormat16; - - const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; - _glView.contentScaleFactor = scaleFactor; - _glView.delegate = self; - [_glView bindDrawable]; - [self insertSubview:_glView atIndex:0]; - - _glView.contentMode = UIViewContentModeCenter; - self.backgroundColor = [UIColor clearColor]; self.clipsToBounds = YES; - // load extensions - // - mbgl::gl::InitializeExtensions([](const char * name) { - static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); - if (!framework) { - throw std::runtime_error("Failed to load OpenGL framework."); - } - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); - void* symbol = CFBundleGetFunctionPointerForName(framework, str); - CFRelease(str); - - return reinterpret_cast(symbol); - }); - // setup mbgl map // + const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; _mbglView = new MBGLView(self, scaleFactor); _mbglFileSource = new mbgl::DefaultFileSource([MGLFileCache obtainSharedCacheWithObject:self]); - // Start paused on the IB canvas + // Start paused _mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous); - if (_isTargetingInterfaceBuilder) { + if (_isTargetingInterfaceBuilder || background) { + self.dormant = YES; _mbglMap->pause(); } @@ -404,7 +374,59 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) }]; } --(void)reachabilityChanged:(NSNotification*)notification +- (void)createGLView +{ + if (_context || [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { + return; + } + + // create context + // + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + NSAssert(_context, @"Failed to create OpenGL ES context."); + + // create GL view + // + _glView = [[GLKView alloc] initWithFrame:self.bounds context:_context]; + _glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _glView.enableSetNeedsDisplay = YES; + _glView.drawableStencilFormat = GLKViewDrawableStencilFormat8; + _glView.drawableDepthFormat = GLKViewDrawableDepthFormat16; + _glView.contentScaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; + _glView.delegate = self; + [_glView bindDrawable]; + [self insertSubview:_glView atIndex:0]; + + _glView.contentMode = UIViewContentModeCenter; + + // load extensions + // + mbgl::gl::InitializeExtensions([](const char * name) { + static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); + if (!framework) { + throw std::runtime_error("Failed to load OpenGL framework."); + } + + CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); + void* symbol = CFBundleGetFunctionPointerForName(framework, str); + CFRelease(str); + + return reinterpret_cast(symbol); + }); +} + +- (void)viewWillEnterForeground +{ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIApplicationWillEnterForegroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIApplicationDidBecomeActiveNotification + object:nil]; + [self commonInit]; +} + +- (void)reachabilityChanged:(NSNotification *)notification { MGLReachability *reachability = [notification object]; if ([reachability isReachable]) { @@ -777,6 +799,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) { MGLAssertIsMainThread(); + [self createGLView]; if (self.isDormant) { self.dormant = NO; From 9e5dd29afeb1c2d562ecb9cad520c8e8ffffe144 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Wed, 8 Jul 2015 15:41:27 -0700 Subject: [PATCH 06/41] bump podspec to 0.5.0-rc.1 w/ symbols --- ios/MapboxGL.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index 5b4597909..fb4ca8518 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.4.5-symbols' + m.version = '0.5.0-rc.1-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' From b8522ba03aec5cc6159a9af26c5e6bed0a6f4f50 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Wed, 8 Jul 2015 15:41:52 -0700 Subject: [PATCH 07/41] [publish ios-v0.5.0-rc.1] From 82cddb5af29d30181c1b61bab6183471456b6d2a Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 08:54:44 -0700 Subject: [PATCH 08/41] fixes #1858: proper shape placement in style layers --- src/mbgl/map/map_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 5b1825bff..aff323d3f 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -206,7 +206,7 @@ void MapContext::updateAnnotationTiles(const std::unordered_settype = (shapeStyle.is() ? StyleLayerType::Line : StyleLayerType::Fill); // add to end of other shape layers just before (last) point layer - style->layers.emplace((style->layers.end() - 2), shapeLayer); + style->layers.emplace((style->layers.end() - 1), shapeLayer); // create shape bucket & connect to source util::ptr shapeBucket = std::make_shared(shapeLayer->type); From 3318a3ced0d0c115e8ba4be40e669619ce4537af Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 09:48:09 -0700 Subject: [PATCH 09/41] refs #1859: use traditional struct declaration --- include/mbgl/map/map.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 72800a9c1..294d0efcd 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -36,14 +36,17 @@ enum class AnnotationType : uint8_t { Shape = 1 << 1, }; +struct EdgeInsets { + double top = 0; + double left = 0; + double bottom = 0; + double right = 0; +}; + using AnnotationIDs = std::vector; using AnnotationSegment = std::vector; using AnnotationSegments = std::vector; -using EdgeInsets = struct { - double top, left, bottom, right; -}; - class Map : private util::noncopyable { friend class View; From 2df80af3d3616c0e174ae1b2e24b5010960bd845 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 13:41:42 -0700 Subject: [PATCH 10/41] Revert "Defer initialization until app enters foreground" This reverts commit 0fd9fe78dbb27cdd8cdea1d664596c226a6273b5. --- platform/ios/MGLMapView.mm | 105 +++++++++++++++---------------------- 1 file changed, 41 insertions(+), 64 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 6220c8971..3fd0ed02c 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -206,28 +206,58 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) - (void)commonInit { _isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent; - - BOOL background = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; - if (!background) - { - [self createGLView]; - } + // create context + // + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + NSAssert(_context, @"Failed to create OpenGL ES context."); + // setup accessibility + // self.accessibilityLabel = @"Map"; + + // create GL view + // + _glView = [[GLKView alloc] initWithFrame:self.bounds context:_context]; + _glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _glView.enableSetNeedsDisplay = YES; + _glView.drawableStencilFormat = GLKViewDrawableStencilFormat8; + _glView.drawableDepthFormat = GLKViewDrawableDepthFormat16; + + const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; + _glView.contentScaleFactor = scaleFactor; + _glView.delegate = self; + [_glView bindDrawable]; + [self insertSubview:_glView atIndex:0]; + + _glView.contentMode = UIViewContentModeCenter; + self.backgroundColor = [UIColor clearColor]; self.clipsToBounds = YES; + // load extensions + // + mbgl::gl::InitializeExtensions([](const char * name) { + static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); + if (!framework) { + throw std::runtime_error("Failed to load OpenGL framework."); + } + + CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); + void* symbol = CFBundleGetFunctionPointerForName(framework, str); + CFRelease(str); + + return reinterpret_cast(symbol); + }); + // setup mbgl map // - const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; _mbglView = new MBGLView(self, scaleFactor); _mbglFileSource = new mbgl::DefaultFileSource([MGLFileCache obtainSharedCacheWithObject:self]); - // Start paused + // Start paused on the IB canvas _mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous); - if (_isTargetingInterfaceBuilder || background) { - self.dormant = YES; + if (_isTargetingInterfaceBuilder) { _mbglMap->pause(); } @@ -374,59 +404,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) }]; } -- (void)createGLView -{ - if (_context || [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { - return; - } - - // create context - // - _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - NSAssert(_context, @"Failed to create OpenGL ES context."); - - // create GL view - // - _glView = [[GLKView alloc] initWithFrame:self.bounds context:_context]; - _glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _glView.enableSetNeedsDisplay = YES; - _glView.drawableStencilFormat = GLKViewDrawableStencilFormat8; - _glView.drawableDepthFormat = GLKViewDrawableDepthFormat16; - _glView.contentScaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; - _glView.delegate = self; - [_glView bindDrawable]; - [self insertSubview:_glView atIndex:0]; - - _glView.contentMode = UIViewContentModeCenter; - - // load extensions - // - mbgl::gl::InitializeExtensions([](const char * name) { - static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); - if (!framework) { - throw std::runtime_error("Failed to load OpenGL framework."); - } - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); - void* symbol = CFBundleGetFunctionPointerForName(framework, str); - CFRelease(str); - - return reinterpret_cast(symbol); - }); -} - -- (void)viewWillEnterForeground -{ - [[NSNotificationCenter defaultCenter] removeObserver:self - name:UIApplicationWillEnterForegroundNotification - object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [self commonInit]; -} - -- (void)reachabilityChanged:(NSNotification *)notification +-(void)reachabilityChanged:(NSNotification*)notification { MGLReachability *reachability = [notification object]; if ([reachability isReachable]) { @@ -799,7 +777,6 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration) { MGLAssertIsMainThread(); - [self createGLView]; if (self.isDormant) { self.dormant = NO; From 7aa83b3c9635b3c952b4d8e3d77dfc48d157f847 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Wed, 8 Jul 2015 22:30:52 -0700 Subject: [PATCH 11/41] test on Xcode 6.4 / iOS 8.4 --- .travis.yml | 4 ++-- scripts/ios/test.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e5b94a813..ccd4cd035 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,10 +25,10 @@ matrix: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] packages: [ 'gdb', 'clang-3.5', 'libstdc++-4.9-dev', 'libstdc++6', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ] - os: osx - osx_image: beta-xcode6.3 + osx_image: beta-xcode6.4 env: FLAVOR=osx BUILDTYPE=Debug - os: osx - osx_image: beta-xcode6.3 + osx_image: beta-xcode6.4 env: FLAVOR=ios BUILDTYPE=Release - os: linux env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Release diff --git a/scripts/ios/test.sh b/scripts/ios/test.sh index bfaed4646..170aa0f64 100755 --- a/scripts/ios/test.sh +++ b/scripts/ios/test.sh @@ -7,5 +7,5 @@ set -u xctool \ -project ./test/ios/ios-tests.xcodeproj \ -scheme 'Mapbox GL Tests' \ - -sdk iphonesimulator8.3 \ + -sdk iphonesimulator8.4 \ test From 5f316975568e03c64873ef496c6ff6ee013d28fa Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 13:58:28 -0700 Subject: [PATCH 12/41] bump podspec to 0.5.0rc2 --- ios/MapboxGL.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index fb4ca8518..896f69c96 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.5.0-rc.1-symbols' + m.version = '0.5.0-rc.2-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' From c780f1617e459e3e13fadff3a34fa3a835908951 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 13:59:11 -0700 Subject: [PATCH 13/41] [publish ios-v0.5.0-rc.2] From 91b2912c2d910dc4ff3ce4258ac742d42f35c907 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 22:27:41 -0700 Subject: [PATCH 14/41] bump podspec to 0.5.0 final (no symbols) --- ios/MapboxGL.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index 896f69c96..c042f4f01 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.5.0-rc.2-symbols' + m.version = '0.5.0' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' From 7d250934b15f85f701d6c28a0a68959fe1144f52 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 22:28:02 -0700 Subject: [PATCH 15/41] [publish ios-v0.5.0] From 4acf6c4268231b09c81dd376f1f672ade1c278d9 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Thu, 9 Jul 2015 22:54:54 -0700 Subject: [PATCH 16/41] updated changelog for 0.5.0 --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07f6672aa..0afd3f64b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.5.0 + +### Core + +- Support for runtime marker imagery. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941)) +- Added `Map::fitBounds()` for region-based viewport setting. ([#1092](https://github.com/mapbox/mapbox-gl-native/issues/1092)) +- Added a raster satellite bundled style and improved raster rendering. ([#963](https://github.com/mapbox/mapbox-gl-native/issues/963)) +- Improved round line joins for semi-transparent lines. ([#1839](https://github.com/mapbox/mapbox-gl-native/pull/1839)) +- Improved map render lifecycle notifications. ([#1026](https://github.com/mapbox/mapbox-gl-native/issues/1026)) +- Fixed a bug that caused annotations not to show at zoom level zero. ([#1279](https://github.com/mapbox/mapbox-gl-native/issues/1279)) +- Fixed a bug with the ordering of shape layers. ([#1866](https://github.com/mapbox/mapbox-gl-native/pull/1866)) +- Other bug fixes and performance improvements. + +### iOS + +- **Breaking:** Removed `-[MGLMapViewDelegate mapView:symbolNameForAnnotation:]` since runtime imagery can be used. ([#1851](https://github.com/mapbox/mapbox-gl-native/issues/1851)) +- **Breaking:** Reversed the compass `direction` polarity to be consistent with other map frameworks. ([#1780](https://github.com/mapbox/mapbox-gl-native/issues/1780)) +- Added `MGLAnnotationImage` and `MGLGeometry` routines. +- Improved `UIView` tracking to the map. ([#1813](https://github.com/mapbox/mapbox-gl-native/pull/1813)) +- Exposed compass, Mapbox logo, and attribution button as hideable views. ([#1770](https://github.com/mapbox/mapbox-gl-native/pull/1770)) +- Build against iOS 8.4. ([#1868](https://github.com/mapbox/mapbox-gl-native/pull/1868)) + ## 0.4.0 ### Core From 9bb50321030a99fcb8215d5a7b78a60772ed3e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 10 Jul 2015 11:33:43 -0700 Subject: [PATCH 17/41] Replaced release notes for 0.5.0 Replaced the release notes with more detailed ones from . This change also fixes a build error due to a reference to a method that had been removed. --- CHANGELOG.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0afd3f64b..5867b2d13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,11 +15,18 @@ ### iOS -- **Breaking:** Removed `-[MGLMapViewDelegate mapView:symbolNameForAnnotation:]` since runtime imagery can be used. ([#1851](https://github.com/mapbox/mapbox-gl-native/issues/1851)) -- **Breaking:** Reversed the compass `direction` polarity to be consistent with other map frameworks. ([#1780](https://github.com/mapbox/mapbox-gl-native/issues/1780)) -- Added `MGLAnnotationImage` and `MGLGeometry` routines. +- **Breaking:** Headers now make use of lightweight generics, eliminating many unnecessary casts when working with annotations in Swift 2.0 in Xcode 7. ([#1711](https://github.com/mapbox/mapbox-gl-native/pull/1711)) +- **Breaking:** `-mapView:symbolNameForAnnotation:` has been removed from the `MGLMapViewDelegate` protocol. Implement `-mapView:imageForAnnotation:` instead, which accepts images at runtime. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941)) +- **Breaking:** `MGLMapView.direction` is now expressed in terms of degrees clockwise from true north, as indicated in the documentation, rather than counterclockwise. ([#1789](https://github.com/mapbox/mapbox-gl-native/pull/1789)) +- A Satellite style showing Mapbox Satellite imagery is now bundled with Mapbox GL. ([#1845](https://github.com/mapbox/mapbox-gl-native/pull/1845)) - Improved `UIView` tracking to the map. ([#1813](https://github.com/mapbox/mapbox-gl-native/pull/1813)) -- Exposed compass, Mapbox logo, and attribution button as hideable views. ([#1770](https://github.com/mapbox/mapbox-gl-native/pull/1770)) +- Delegate method `-[MGLMapViewDelegate mapView:didFailToLocateUserWithError:]` now works. ([#1608](https://github.com/mapbox/mapbox-gl-native/pull/1608)) +- It is now possible to fit the map’s viewport to a coordinate bounding box via `-[MGLMapView setVisibleCoordinateBounds:animated:]` or to a specific set of coordinates via `-[MGLMapView setVisibleCoordinates:count:edgePadding:animated:]`. ([#1783](https://github.com/mapbox/mapbox-gl-native/pull/1783), [#1795](https://github.com/mapbox/mapbox-gl-native/pull/1795)) +- The logo and ℹ️ no longer disappear or get distorted after embedding MGLMapView in a different view, and you can now access these subviews directly via properties on MGLMapView. ([#1779](https://github.com/mapbox/mapbox-gl-native/pull/1779), [#1815](https://github.com/mapbox/mapbox-gl-native/pull/1815)) +- Raster tiles now look sharper midway between two zoom levels. ([#1843](https://github.com/mapbox/mapbox-gl-native/pull/1843)) +- Resetting the map rotation to north no longer also resets the user location tracking mode. ([#1809](https://github.com/mapbox/mapbox-gl-native/pull/1809)) +- `-[MGLMapView convertPoint:toCoordinateFromView:]` now returns accurate coordinates on iPhone 6. ([#1827](https://github.com/mapbox/mapbox-gl-native/pull/1827)) +- Fixed an issue in which `-[MGLMapView direction]` would sometimes return 360 instead of 0. ([#1829](https://github.com/mapbox/mapbox-gl-native/pull/1829)) - Build against iOS 8.4. ([#1868](https://github.com/mapbox/mapbox-gl-native/pull/1868)) ## 0.4.0 From 06fd6d5c1e3ba2fb0c7dc899406ec5a90174a906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 10 Jul 2015 11:42:46 -0700 Subject: [PATCH 18/41] Cherry-picked part of 987d961e5bd2a7b9a68c4f05dd8b599eb1357add to fix the build --- platform/ios/MGLMapboxEvents.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index eb8d909db..314d50dd0 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -604,10 +604,7 @@ const NSTimeInterval MGLFlushInterval = 60; [request setHTTPBody:jsonData]; // Send non blocking HTTP Request to server - NSURLSessionDataTask *task = [_session dataTaskWithRequest:request completionHandler:^(__unused NSData * __nullable data, __unused NSURLResponse * __nullable response, __unused NSError * __nullable error) - { - }]; - [task resume]; + [[_session dataTaskWithRequest:request] resume]; } }); } From 97b7307f3519ecd749502043281e918287c0b616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 10 Jul 2015 10:45:55 -0700 Subject: [PATCH 19/41] Force -ObjC in Mapbox GL pod Fixes #1849. --- ios/MapboxGL.podspec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index c042f4f01..e581312e7 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -29,6 +29,9 @@ Pod::Spec.new do |m| m.frameworks = 'CoreLocation', 'CoreTelephony', 'GLKit', 'ImageIO', 'MobileCoreServices', 'QuartzCore', 'SystemConfiguration' m.libraries = 'c++', 'sqlite3', 'z' - m.xcconfig = { 'OTHER_CPLUSPLUSFLAGS' => '-std=gnu++11 -stdlib=libc++' } + m.xcconfig = { + 'OTHER_CPLUSPLUSFLAGS' => '-std=gnu++11 -stdlib=libc++', + 'OTHER_LDFLAGS' => '-ObjC', + } end From 1350ed76540781823e584ec996cace3895021430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sat, 11 Jul 2015 15:57:11 -0700 Subject: [PATCH 20/41] Fetch tags before relying on a list of them Cherry-picked from 482b8bde6314b38c061040fe2f885bc2068014b1 to fix the build. --- scripts/ios/package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ios/package.sh b/scripts/ios/package.sh index 25306bb06..91e70dbba 100755 --- a/scripts/ios/package.sh +++ b/scripts/ios/package.sh @@ -109,6 +109,7 @@ if [ -z `which appledoc` ]; then exit 1 fi DOCS_OUTPUT="${OUTPUT}/static/Docs" +git fetch --tags DOCS_VERSION=$( git tag --sort -v:refname | grep -v '\-rc.' | sed -n '1p' | sed 's/^v//' ) rm -rf /tmp/mbgl mkdir -p /tmp/mbgl/ From c066931a49adc3b78a2f8c31e500dc3073c394c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sat, 11 Jul 2015 15:14:16 -0700 Subject: [PATCH 21/41] Opt into Xcode 6.4 Cherry-picked from 5f7575dd8feea880fd4ab1c414e281db2ef66cf6 to fix the build. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ccd4cd035..f25079de5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,10 +25,10 @@ matrix: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ] packages: [ 'gdb', 'clang-3.5', 'libstdc++-4.9-dev', 'libstdc++6', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ] - os: osx - osx_image: beta-xcode6.4 + osx_image: xcode6.4 env: FLAVOR=osx BUILDTYPE=Debug - os: osx - osx_image: beta-xcode6.4 + osx_image: xcode6.4 env: FLAVOR=ios BUILDTYPE=Release - os: linux env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Release From b65f30966bb05ebcff4dd6add0c7ea149cd1bdfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 13 Jul 2015 10:15:33 -0700 Subject: [PATCH 22/41] Updated changelog for 0.5.1 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5867b2d13..45b1959a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.5.1 + +### iOS + +- Added support for CocoaPods 0.38.0. ([#1876](https://github.com/mapbox/mapbox-gl-native/pull/1876)) + ## 0.5.0 ### Core From 970ad1fe1b25cd2fc6e33f84e890ddd90f6874f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 13 Jul 2015 10:50:51 -0700 Subject: [PATCH 23/41] Updated podspec for 0.5.1 --- ios/MapboxGL.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index e581312e7..a49fb7deb 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.5.0' + m.version = '0.5.1' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' From f5e38ee21a0d6db9e7d21bf4e904b5e76789c9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 13 Jul 2015 10:52:57 -0700 Subject: [PATCH 24/41] [publish ios-v0.5.1] From 938165de174e9dbec523739378122b4f970a2ac0 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 14 Jul 2015 14:26:40 +0300 Subject: [PATCH 25/41] Re-enable the Satellite style on the Linux/OSX app --- platform/default/default_styles.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/default/default_styles.cpp b/platform/default/default_styles.cpp index a631008a4..e25d96e4c 100644 --- a/platform/default/default_styles.cpp +++ b/platform/default/default_styles.cpp @@ -7,7 +7,8 @@ const std::vector> defaultStyles = { { "asset://styles/mapbox-streets-v7.json", "Mapbox Streets" }, { "asset://styles/emerald-v7.json", "Emerald" }, { "asset://styles/light-v7.json", "Light" }, - { "asset://styles/dark-v7.json", "Dark" } + { "asset://styles/dark-v7.json", "Dark" }, + { "asset://styles/satellite-v7.json", "Satellite" } }; } // end namespace util From 77a91f64d8afb08a6d3e48da4348f6e9f7c67e69 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Sun, 12 Jul 2015 14:09:49 +0300 Subject: [PATCH 26/41] Micro-optimizations to Style --- src/mbgl/style/style_layer.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp index 8713b73b1..c29c3ee28 100644 --- a/src/mbgl/style/style_layer.cpp +++ b/src/mbgl/style/style_layer.cpp @@ -273,18 +273,11 @@ bool StyleLayer::hasTransitions() const { void StyleLayer::cleanupAppliedStyleProperties(TimePoint now) { - auto it = appliedStyle.begin(); - const auto end = appliedStyle.end(); - while (it != end) { - AppliedClassProperties &applied_properties = it->second; - applied_properties.cleanup(now); - + for (auto it = appliedStyle.begin(); it != appliedStyle.end();) { + AppliedClassProperties& appliedPropertyValues = it->second; + appliedPropertyValues.cleanup(now); // If the current properties object is empty, remove it from the map entirely. - if (applied_properties.empty()) { - appliedStyle.erase(it++); - } else { - ++it; - } + appliedPropertyValues.empty() ? appliedStyle.erase(it++) : ++it; } } From 7023ea061c79468843178a636cb83e8c5044a1e5 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Sun, 12 Jul 2015 22:00:32 +0300 Subject: [PATCH 27/41] Unify time point for Mapcontext::update - Let style classes cascade use the same time point as the one used to recalculate style. - Cleaned up MapContext::update to return early whenever possible. - Cleaned up MapContext::loadStyleJSON to avoid redundant calls to style classes cascade. --- src/mbgl/map/map_context.cpp | 48 +++++++++++++++++------------------- src/mbgl/map/map_context.hpp | 3 --- src/mbgl/style/style.cpp | 4 +-- src/mbgl/style/style.hpp | 2 +- 4 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 4447ecc4f..fc700581d 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -131,10 +131,10 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base) assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); style->setJSON(json, base); - style->cascade(data.getClasses()); - style->setDefaultTransitionDuration(data.getDefaultTransitionDuration()); style->setObserver(this); + updated |= static_cast(Update::DefaultTransitionDuration); + updated |= static_cast(Update::Classes); updated |= static_cast(Update::Zoom); asyncUpdate->send(); @@ -240,45 +240,43 @@ void MapContext::updateAnnotationTiles(const std::unordered_set(Update::Classes); asyncUpdate->send(); annotationManager->resetStaleTiles(); } -void MapContext::cascadeClasses() { - style->cascade(data.getClasses()); -} - void MapContext::update() { assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); - const auto now = Clock::now(); + if (!style) { + updated = static_cast(Update::Nothing); + return; + } + + TimePoint now = Clock::now(); + data.setAnimationTime(now); - if (style) { - if (updated & static_cast(Update::DefaultTransitionDuration)) { - style->setDefaultTransitionDuration(data.getDefaultTransitionDuration()); - } + if (updated & static_cast(Update::DefaultTransitionDuration)) { + style->setDefaultTransitionDuration(data.getDefaultTransitionDuration()); + } - if (updated & static_cast(Update::Classes)) { - cascadeClasses(); - } + if (updated & static_cast(Update::Classes)) { + style->cascade(data.getClasses(), now); + } - if (updated & static_cast(Update::Classes) || + if (updated & static_cast(Update::Classes) || updated & static_cast(Update::Zoom)) { - style->recalculate(transformState.getNormalizedZoom(), now); - } + style->recalculate(transformState.getNormalizedZoom(), now); + } - style->update(transformState, *texturePool); + style->update(transformState, *texturePool); - if (data.mode == MapMode::Continuous) { - view.invalidate(); - } else if (callback && style->isLoaded()) { - renderSync(transformState, frameData); - } + if (data.mode == MapMode::Continuous) { + view.invalidate(); + } else if (callback && style->isLoaded()) { + renderSync(transformState, frameData); } updated = static_cast(Update::Nothing); diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp index 2e60d8eae..8c8c90ff8 100644 --- a/src/mbgl/map/map_context.hpp +++ b/src/mbgl/map/map_context.hpp @@ -72,9 +72,6 @@ public: void onResourceLoadingFailed(std::exception_ptr error) override; private: - // Style-related updates. - void cascadeClasses(); - // Update the state indicated by the accumulated Update flags, then render. void update(); diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index e091c92f5..4e0c41185 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -86,9 +86,7 @@ void Style::update(const TransformState& transform, } } -void Style::cascade(const std::vector& classes) { - TimePoint now = Clock::now(); - +void Style::cascade(const std::vector& classes, TimePoint now) { for (const auto& layer : layers) { layer->setClasses(classes, now, defaultTransition); } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index d6b762a83..850c06659 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -54,7 +54,7 @@ public: // a tile is ready so observers can render the tile. void update(const TransformState&, TexturePool&); - void cascade(const std::vector&); + void cascade(const std::vector&, TimePoint now); void recalculate(float z, TimePoint now); void setDefaultTransitionDuration(Duration); From 7d8b4dc6c0714aa43a85a56ea32fa5590dd843e6 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Mon, 13 Jul 2015 03:15:14 +0300 Subject: [PATCH 28/41] s/properties/propertyValues/ This list stores different values for the same property, but the property itself remains the same. --- src/mbgl/style/applied_class_properties.cpp | 14 +++++++------- src/mbgl/style/applied_class_properties.hpp | 4 ++-- src/mbgl/style/style_layer.cpp | 5 ++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/mbgl/style/applied_class_properties.cpp b/src/mbgl/style/applied_class_properties.cpp index d42102b2a..f0680dd0f 100644 --- a/src/mbgl/style/applied_class_properties.cpp +++ b/src/mbgl/style/applied_class_properties.cpp @@ -10,15 +10,15 @@ AppliedClassProperty::AppliedClassProperty(ClassID class_id, TimePoint begin_, T // Returns the ID of the most recent ClassID AppliedClassProperties::mostRecent() const { - return properties.size() ? properties.back().name : ClassID::Fallback; + return propertyValues.empty() ? ClassID::Fallback : propertyValues.back().name; } void AppliedClassProperties::add(ClassID class_id, TimePoint begin, TimePoint end, const PropertyValue &value) { - properties.emplace_back(class_id, begin, end, value); + propertyValues.emplace_back(class_id, begin, end, value); } bool AppliedClassProperties::hasTransitions() const { - return properties.size() > 1; + return propertyValues.size() > 1; } // Erase all items in the property list that are before a completed transition. @@ -26,19 +26,19 @@ bool AppliedClassProperties::hasTransitions() const { void AppliedClassProperties::cleanup(TimePoint now) { // Iterate backwards, but without using the rbegin/rend interface since we need forward // iterators to use .erase(). - for (auto it = properties.end(), begin = properties.begin(); it != begin;) { + for (auto it = propertyValues.end(), begin = propertyValues.begin(); it != begin;) { // If the property is finished, break iteration and delete all remaining items. if ((--it)->end <= now) { // Removes all items that precede the current iterator, but *not* the element currently // pointed to by the iterator. This preserves the last completed transition as the // first element in the property list. - properties.erase(begin, it); + propertyValues.erase(begin, it); // Also erase the pivot element if it's a fallback value. This means we can remove the // entire applied properties object as well, because we already have the fallback // value set as the default. if (it->name == ClassID::Fallback) { - properties.erase(it); + propertyValues.erase(it); } break; } @@ -46,7 +46,7 @@ void AppliedClassProperties::cleanup(TimePoint now) { } bool AppliedClassProperties::empty() const { - return properties.empty(); + return propertyValues.empty(); } } diff --git a/src/mbgl/style/applied_class_properties.hpp b/src/mbgl/style/applied_class_properties.hpp index 6a0d2a6fb..350bb846c 100644 --- a/src/mbgl/style/applied_class_properties.hpp +++ b/src/mbgl/style/applied_class_properties.hpp @@ -23,14 +23,14 @@ public: class AppliedClassProperties { public: - std::list properties; + std::list propertyValues; public: // Returns the ID of the most recent ClassID mostRecent() const; void add(ClassID class_id, TimePoint begin, TimePoint end, const PropertyValue &value); - bool hasTransitions() const; void cleanup(TimePoint now); + bool hasTransitions() const; bool empty() const; }; diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp index c29c3ee28..7f9c7ecbf 100644 --- a/src/mbgl/style/style_layer.cpp +++ b/src/mbgl/style/style_layer.cpp @@ -140,7 +140,7 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c AppliedClassProperties &applied = it->second; // Iterate through all properties that we need to apply in order. const PropertyEvaluator evaluator(z, zoomHistory); - for (auto& property : applied.properties) { + for (auto& property : applied.propertyValues) { if (now >= property.begin) { // We overwrite the current property with the new value. target = mapbox::util::apply_visitor(evaluator, property.value); @@ -158,7 +158,7 @@ void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, cons AppliedClassProperties &applied = it->second; // Iterate through all properties that we need to apply in order. const PropertyEvaluator evaluator(z, zoomHistory); - for (auto& property : applied.properties) { + for (auto& property : applied.propertyValues) { if (now >= property.end) { // We overwrite the current property with the new value. target = mapbox::util::apply_visitor(evaluator, property.value); @@ -271,7 +271,6 @@ bool StyleLayer::hasTransitions() const { return false; } - void StyleLayer::cleanupAppliedStyleProperties(TimePoint now) { for (auto it = appliedStyle.begin(); it != appliedStyle.end();) { AppliedClassProperties& appliedPropertyValues = it->second; From 2aad2f4e14ab762847141788e725d50e1ee44ace Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Mon, 13 Jul 2015 15:15:50 +0300 Subject: [PATCH 29/41] Pass {Duration,TimePoint} by const ref if possible --- include/mbgl/map/map.hpp | 24 ++++++++--------- src/mbgl/map/map.cpp | 24 ++++++++--------- src/mbgl/map/map_context.cpp | 2 +- src/mbgl/map/map_data.hpp | 5 ++-- src/mbgl/map/transform.cpp | 30 ++++++++++----------- src/mbgl/map/transform.hpp | 30 ++++++++++----------- src/mbgl/renderer/frame_history.cpp | 6 ++--- src/mbgl/renderer/frame_history.hpp | 10 +++---- src/mbgl/renderer/painter.cpp | 2 +- src/mbgl/renderer/painter.hpp | 2 +- src/mbgl/style/applied_class_properties.cpp | 6 ++--- src/mbgl/style/applied_class_properties.hpp | 6 ++--- src/mbgl/style/style.cpp | 4 +-- src/mbgl/style/style.hpp | 4 +-- src/mbgl/style/style_layer.cpp | 24 ++++++++--------- src/mbgl/style/style_layer.hpp | 14 +++++----- src/mbgl/style/zoom_history.hpp | 4 +-- src/mbgl/util/transition.cpp | 2 +- src/mbgl/util/transition.hpp | 14 +++++----- 19 files changed, 107 insertions(+), 106 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index c6d5e1475..d31d6a275 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -79,8 +79,8 @@ public: void setClasses(const std::vector&); std::vector getClasses() const; - void setDefaultTransitionDuration(Duration = Duration::zero()); - Duration getDefaultTransitionDuration(); + void setDefaultTransitionDuration(const Duration& = Duration::zero()); + Duration getDefaultTransitionDuration() const; void setStyleURL(const std::string& url); void setStyleJSON(const std::string& json, const std::string& base = ""); std::string getStyleURL() const; @@ -91,27 +91,27 @@ public: void setGestureInProgress(bool); // Position - void moveBy(double dx, double dy, Duration = Duration::zero()); - void setLatLng(LatLng latLng, Duration = Duration::zero()); + void moveBy(double dx, double dy, const Duration& = Duration::zero()); + void setLatLng(LatLng latLng, const Duration& = Duration::zero()); LatLng getLatLng() const; void resetPosition(); // Scale - void scaleBy(double ds, double cx = -1, double cy = -1, Duration = Duration::zero()); - void setScale(double scale, double cx = -1, double cy = -1, Duration = Duration::zero()); + void scaleBy(double ds, double cx = -1, double cy = -1, const Duration& = Duration::zero()); + void setScale(double scale, double cx = -1, double cy = -1, const Duration& = Duration::zero()); double getScale() const; - void setZoom(double zoom, Duration = Duration::zero()); + void setZoom(double zoom, const Duration& = Duration::zero()); double getZoom() const; - void setLatLngZoom(LatLng latLng, double zoom, Duration = Duration::zero()); - void fitBounds(LatLngBounds bounds, EdgeInsets padding, Duration duration = Duration::zero()); - void fitBounds(AnnotationSegment segment, EdgeInsets padding, Duration duration = Duration::zero()); + void setLatLngZoom(LatLng latLng, double zoom, const Duration& = Duration::zero()); + void fitBounds(LatLngBounds bounds, EdgeInsets padding, const Duration& duration = Duration::zero()); + void fitBounds(AnnotationSegment segment, EdgeInsets padding, const Duration& duration = Duration::zero()); void resetZoom(); double getMinZoom() const; double getMaxZoom() const; // Rotation - void rotateBy(double sx, double sy, double ex, double ey, Duration = Duration::zero()); - void setBearing(double degrees, Duration = Duration::zero()); + void rotateBy(double sx, double sy, double ex, double ey, const Duration& = Duration::zero()); + void setBearing(double degrees, const Duration& = Duration::zero()); void setBearing(double degrees, double cx, double cy); double getBearing() const; void resetNorth(); diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 37cd3be33..0e58a2912 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -116,12 +116,12 @@ void Map::setGestureInProgress(bool inProgress) { #pragma mark - Position -void Map::moveBy(double dx, double dy, Duration duration) { +void Map::moveBy(double dx, double dy, const Duration& duration) { transform->moveBy(dx, dy, duration); update(); } -void Map::setLatLng(LatLng latLng, Duration duration) { +void Map::setLatLng(LatLng latLng, const Duration& duration) { transform->setLatLng(latLng, duration); update(); } @@ -140,12 +140,12 @@ void Map::resetPosition() { #pragma mark - Scale -void Map::scaleBy(double ds, double cx, double cy, Duration duration) { +void Map::scaleBy(double ds, double cx, double cy, const Duration& duration) { transform->scaleBy(ds, cx, cy, duration); update(Update::Zoom); } -void Map::setScale(double scale, double cx, double cy, Duration duration) { +void Map::setScale(double scale, double cx, double cy, const Duration& duration) { transform->setScale(scale, cx, cy, duration); update(Update::Zoom); } @@ -154,7 +154,7 @@ double Map::getScale() const { return transform->getScale(); } -void Map::setZoom(double zoom, Duration duration) { +void Map::setZoom(double zoom, const Duration& duration) { transform->setZoom(zoom, duration); update(Update::Zoom); } @@ -163,12 +163,12 @@ double Map::getZoom() const { return transform->getZoom(); } -void Map::setLatLngZoom(LatLng latLng, double zoom, Duration duration) { +void Map::setLatLngZoom(LatLng latLng, double zoom, const Duration& duration) { transform->setLatLngZoom(latLng, zoom, duration); update(Update::Zoom); } -void Map::fitBounds(LatLngBounds bounds, EdgeInsets padding, Duration duration) { +void Map::fitBounds(LatLngBounds bounds, EdgeInsets padding, const Duration& duration) { AnnotationSegment segment = { {bounds.ne.latitude, bounds.sw.longitude}, bounds.sw, @@ -178,7 +178,7 @@ void Map::fitBounds(LatLngBounds bounds, EdgeInsets padding, Duration duration) fitBounds(segment, padding, duration); } -void Map::fitBounds(AnnotationSegment segment, EdgeInsets padding, Duration duration) { +void Map::fitBounds(AnnotationSegment segment, EdgeInsets padding, const Duration& duration) { if (segment.empty()) { return; } @@ -243,12 +243,12 @@ uint16_t Map::getHeight() const { #pragma mark - Rotation -void Map::rotateBy(double sx, double sy, double ex, double ey, Duration duration) { +void Map::rotateBy(double sx, double sy, double ex, double ey, const Duration& duration) { transform->rotateBy(sx, sy, ex, ey, duration); update(); } -void Map::setBearing(double degrees, Duration duration) { +void Map::setBearing(double degrees, const Duration& duration) { transform->setAngle(-degrees * M_PI / 180, duration); update(); } @@ -416,12 +416,12 @@ std::vector Map::getClasses() const { return data->getClasses(); } -void Map::setDefaultTransitionDuration(Duration duration) { +void Map::setDefaultTransitionDuration(const Duration& duration) { data->setDefaultTransitionDuration(duration); update(Update::DefaultTransitionDuration); } -Duration Map::getDefaultTransitionDuration() { +Duration Map::getDefaultTransitionDuration() const { return data->getDefaultTransitionDuration(); } diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index fc700581d..7f2fe4e98 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -254,7 +254,7 @@ void MapContext::update() { return; } - TimePoint now = Clock::now(); + const TimePoint now = Clock::now(); data.setAnimationTime(now); diff --git a/src/mbgl/map/map_data.hpp b/src/mbgl/map/map_data.hpp index 75ada0615..1703aff8c 100644 --- a/src/mbgl/map/map_data.hpp +++ b/src/mbgl/map/map_data.hpp @@ -69,14 +69,15 @@ public: // has a bug that doesn't allow TimePoints to be atomic. return TimePoint(animationTime); } - inline void setAnimationTime(TimePoint timePoint) { + inline void setAnimationTime(const TimePoint& timePoint) { animationTime = timePoint.time_since_epoch(); }; inline Duration getDefaultTransitionDuration() const { return defaultTransitionDuration; } - inline void setDefaultTransitionDuration(Duration duration) { + + inline void setDefaultTransitionDuration(const Duration& duration) { defaultTransitionDuration = duration; } diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 12698a1e8..b39614888 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -53,7 +53,7 @@ bool Transform::resize(const std::array size) { #pragma mark - Position -void Transform::moveBy(const double dx, const double dy, const Duration duration) { +void Transform::moveBy(const double dx, const double dy, const Duration& duration) { if (std::isnan(dx) || std::isnan(dy)) { return; } @@ -61,7 +61,7 @@ void Transform::moveBy(const double dx, const double dy, const Duration duration _moveBy(dx, dy, duration); } -void Transform::_moveBy(const double dx, const double dy, const Duration duration) { +void Transform::_moveBy(const double dx, const double dy, const Duration& duration) { double x = state.x + std::cos(state.angle) * dx + std::sin( state.angle) * dy; double y = state.y + std::cos(state.angle) * dy + std::sin(-state.angle) * dx; @@ -95,7 +95,7 @@ void Transform::_moveBy(const double dx, const double dy, const Duration duratio } } -void Transform::setLatLng(const LatLng latLng, const Duration duration) { +void Transform::setLatLng(const LatLng latLng, const Duration& duration) { if (std::isnan(latLng.latitude) || std::isnan(latLng.longitude)) { return; } @@ -109,7 +109,7 @@ void Transform::setLatLng(const LatLng latLng, const Duration duration) { _setScaleXY(state.scale, xn, yn, duration); } -void Transform::setLatLngZoom(const LatLng latLng, const double zoom, const Duration duration) { +void Transform::setLatLngZoom(const LatLng latLng, const double zoom, const Duration& duration) { if (std::isnan(latLng.latitude) || std::isnan(latLng.longitude) || std::isnan(zoom)) { return; } @@ -132,7 +132,7 @@ void Transform::setLatLngZoom(const LatLng latLng, const double zoom, const Dura #pragma mark - Zoom -void Transform::scaleBy(const double ds, const double cx, const double cy, const Duration duration) { +void Transform::scaleBy(const double ds, const double cx, const double cy, const Duration& duration) { if (std::isnan(ds) || std::isnan(cx) || std::isnan(cy)) { return; } @@ -149,7 +149,7 @@ void Transform::scaleBy(const double ds, const double cx, const double cy, const } void Transform::setScale(const double scale, const double cx, const double cy, - const Duration duration) { + const Duration& duration) { if (std::isnan(scale) || std::isnan(cx) || std::isnan(cy)) { return; } @@ -157,7 +157,7 @@ void Transform::setScale(const double scale, const double cx, const double cy, _setScale(scale, cx, cy, duration); } -void Transform::setZoom(const double zoom, const Duration duration) { +void Transform::setZoom(const double zoom, const Duration& duration) { if (std::isnan(zoom)) { return; } @@ -173,7 +173,7 @@ double Transform::getScale() const { return state.scale; } -void Transform::_setScale(double new_scale, double cx, double cy, const Duration duration) { +void Transform::_setScale(double new_scale, double cx, double cy, const Duration& duration) { // Ensure that we don't zoom in further than the maximum allowed. if (new_scale < state.min_scale) { new_scale = state.min_scale; @@ -205,7 +205,7 @@ void Transform::_setScale(double new_scale, double cx, double cy, const Duration } void Transform::_setScaleXY(const double new_scale, const double xn, const double yn, - const Duration duration) { + const Duration& duration) { double scale = new_scale; double x = xn; double y = yn; @@ -254,7 +254,7 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl #pragma mark - Angle void Transform::rotateBy(const double start_x, const double start_y, const double end_x, - const double end_y, const Duration duration) { + const double end_y, const Duration& duration) { if (std::isnan(start_x) || std::isnan(start_y) || std::isnan(end_x) || std::isnan(end_y)) { return; } @@ -286,7 +286,7 @@ void Transform::rotateBy(const double start_x, const double start_y, const doubl _setAngle(ang, duration); } -void Transform::setAngle(const double new_angle, const Duration duration) { +void Transform::setAngle(const double new_angle, const Duration& duration) { if (std::isnan(new_angle)) { return; } @@ -314,7 +314,7 @@ void Transform::setAngle(const double new_angle, const double cx, const double c } } -void Transform::_setAngle(double new_angle, const Duration duration) { +void Transform::_setAngle(double new_angle, const Duration& duration) { double angle = _normalizeAngle(new_angle, state.angle); state.angle = _normalizeAngle(state.angle, angle); @@ -352,7 +352,7 @@ double Transform::getAngle() const { void Transform::startTransition(std::function frame, std::function finish, - Duration duration) { + const Duration& duration) { if (transitionFinishFn) { transitionFinishFn(); } @@ -360,7 +360,7 @@ void Transform::startTransition(std::function frame, transitionStart = Clock::now(); transitionDuration = duration; - transitionFrameFn = [frame, this](TimePoint now) { + transitionFrameFn = [frame, this](const TimePoint now) { float t = std::chrono::duration(now - transitionStart) / transitionDuration; if (t >= 1.0) { Update result = frame(1.0); @@ -381,7 +381,7 @@ bool Transform::needsTransition() const { return !!transitionFrameFn; } -UpdateType Transform::updateTransitions(const TimePoint now) { +UpdateType Transform::updateTransitions(const TimePoint& now) { return static_cast(transitionFrameFn ? transitionFrameFn(now) : Update::Nothing); } diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index c2c4aad2d..badb811af 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -23,27 +23,27 @@ public: bool resize(std::array size); // Position - void moveBy(double dx, double dy, Duration = Duration::zero()); - void setLatLng(LatLng latLng, Duration = Duration::zero()); - void setLatLngZoom(LatLng latLng, double zoom, Duration = Duration::zero()); + void moveBy(double dx, double dy, const Duration& = Duration::zero()); + void setLatLng(LatLng latLng, const Duration& = Duration::zero()); + void setLatLngZoom(LatLng latLng, double zoom, const Duration& = Duration::zero()); inline const LatLng getLatLng() const { return state.getLatLng(); } // Zoom - void scaleBy(double ds, double cx = -1, double cy = -1, Duration = Duration::zero()); - void setScale(double scale, double cx = -1, double cy = -1, Duration = Duration::zero()); - void setZoom(double zoom, Duration = Duration::zero()); + void scaleBy(double ds, double cx = -1, double cy = -1, const Duration& = Duration::zero()); + void setScale(double scale, double cx = -1, double cy = -1, const Duration& = Duration::zero()); + void setZoom(double zoom, const Duration& = Duration::zero()); double getZoom() const; double getScale() const; // Angle - void rotateBy(double sx, double sy, double ex, double ey, Duration = Duration::zero()); - void setAngle(double angle, Duration = Duration::zero()); + void rotateBy(double sx, double sy, double ex, double ey, const Duration& = Duration::zero()); + void setAngle(double angle, const Duration& = Duration::zero()); void setAngle(double angle, double cx, double cy); double getAngle() const; // Transitions bool needsTransition() const; - UpdateType updateTransitions(TimePoint now); + UpdateType updateTransitions(const TimePoint& now); void cancelTransitions(); // Gesture @@ -53,10 +53,10 @@ public: const TransformState getState() const { return state; } private: - void _moveBy(double dx, double dy, Duration = Duration::zero()); - void _setScale(double scale, double cx, double cy, Duration = Duration::zero()); - void _setScaleXY(double new_scale, double xn, double yn, Duration = Duration::zero()); - void _setAngle(double angle, Duration = Duration::zero()); + void _moveBy(double dx, double dy, const Duration& = Duration::zero()); + void _setScale(double scale, double cx, double cy, const Duration& = Duration::zero()); + void _setScaleXY(double new_scale, double xn, double yn, const Duration& = Duration::zero()); + void _setAngle(double angle, const Duration& = Duration::zero()); View &view; @@ -64,11 +64,11 @@ private: void startTransition(std::function frame, std::function finish, - Duration); + const Duration& duration); TimePoint transitionStart; Duration transitionDuration; - std::function transitionFrameFn; + std::function transitionFrameFn; std::function transitionFinishFn; }; diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp index 478520c51..cb36a1d83 100644 --- a/src/mbgl/renderer/frame_history.cpp +++ b/src/mbgl/renderer/frame_history.cpp @@ -3,7 +3,7 @@ using namespace mbgl; // Record frame history that will be used to calculate fading params -void FrameHistory::record(TimePoint now, float zoom) { +void FrameHistory::record(const TimePoint& now, float zoom) { // first frame ever if (!history.size()) { history.emplace_back(FrameSnapshot{TimePoint::min(), zoom}); @@ -15,7 +15,7 @@ void FrameHistory::record(TimePoint now, float zoom) { } } -bool FrameHistory::needsAnimation(const Duration duration) const { +bool FrameHistory::needsAnimation(const Duration& duration) const { if (!history.size()) { return false; } @@ -47,7 +47,7 @@ bool FrameHistory::needsAnimation(const Duration duration) const { return false; } -FadeProperties FrameHistory::getFadeProperties(Duration duration) { +FadeProperties FrameHistory::getFadeProperties(const Duration& duration) { const TimePoint currentTime = Clock::now(); // Remove frames until only one is outside the duration, or until there are only three diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp index 15ca92e46..ef52b2a5e 100644 --- a/src/mbgl/renderer/frame_history.hpp +++ b/src/mbgl/renderer/frame_history.hpp @@ -11,8 +11,8 @@ namespace mbgl { struct FrameSnapshot { - explicit inline FrameSnapshot(TimePoint now_, float z_) : now(now_), z(z_) {} - TimePoint now; + explicit inline FrameSnapshot(const TimePoint& now_, float z_) : now(now_), z(z_) {} + const TimePoint now; float z; }; @@ -26,10 +26,10 @@ struct FadeProperties { class FrameHistory { public: // Record frame history that will be used to calculate fading params - void record(TimePoint now, float zoom); + void record(const TimePoint& now, float zoom); - bool needsAnimation(Duration) const; - FadeProperties getFadeProperties(Duration); + bool needsAnimation(const Duration& duration) const; + FadeProperties getFadeProperties(const Duration& duration); public: std::deque history; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 33f1687a9..77ee868c3 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -165,7 +165,7 @@ void Painter::prepareTile(const Tile& tile) { config.stencilFunc = { GL_EQUAL, ref, mask }; } -void Painter::render(const Style& style, TransformState state_, const FrameData& frame_, TimePoint time) { +void Painter::render(const Style& style, TransformState state_, const FrameData& frame_, const TimePoint& time) { state = state_; frame = frame_; diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index f7342b15c..3719b7f2a 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -96,7 +96,7 @@ public: void render(const Style& style, TransformState state, const FrameData& frame, - TimePoint time); + const TimePoint& time); // Renders debug information for a tile. void renderTileDebug(const Tile& tile); diff --git a/src/mbgl/style/applied_class_properties.cpp b/src/mbgl/style/applied_class_properties.cpp index f0680dd0f..6df075b20 100644 --- a/src/mbgl/style/applied_class_properties.cpp +++ b/src/mbgl/style/applied_class_properties.cpp @@ -2,7 +2,7 @@ namespace mbgl { -AppliedClassProperty::AppliedClassProperty(ClassID class_id, TimePoint begin_, TimePoint end_, const PropertyValue &value_) +AppliedClassProperty::AppliedClassProperty(ClassID class_id, const TimePoint& begin_, const TimePoint& end_, const PropertyValue &value_) : name(class_id), begin(begin_), end(end_), @@ -13,7 +13,7 @@ ClassID AppliedClassProperties::mostRecent() const { return propertyValues.empty() ? ClassID::Fallback : propertyValues.back().name; } -void AppliedClassProperties::add(ClassID class_id, TimePoint begin, TimePoint end, const PropertyValue &value) { +void AppliedClassProperties::add(ClassID class_id, const TimePoint& begin, const TimePoint& end, const PropertyValue &value) { propertyValues.emplace_back(class_id, begin, end, value); } @@ -23,7 +23,7 @@ bool AppliedClassProperties::hasTransitions() const { // Erase all items in the property list that are before a completed transition. // Then, if the only remaining property is a Fallback value, remove it too. -void AppliedClassProperties::cleanup(TimePoint now) { +void AppliedClassProperties::cleanup(const TimePoint& now) { // Iterate backwards, but without using the rbegin/rend interface since we need forward // iterators to use .erase(). for (auto it = propertyValues.end(), begin = propertyValues.begin(); it != begin;) { diff --git a/src/mbgl/style/applied_class_properties.hpp b/src/mbgl/style/applied_class_properties.hpp index 350bb846c..fbba96614 100644 --- a/src/mbgl/style/applied_class_properties.hpp +++ b/src/mbgl/style/applied_class_properties.hpp @@ -11,7 +11,7 @@ namespace mbgl { class AppliedClassProperty { public: - AppliedClassProperty(ClassID class_id, TimePoint begin, TimePoint end, const PropertyValue &value); + AppliedClassProperty(ClassID class_id, const TimePoint& begin, const TimePoint& end, const PropertyValue &value); public: const ClassID name; @@ -28,8 +28,8 @@ public: public: // Returns the ID of the most recent ClassID mostRecent() const; - void add(ClassID class_id, TimePoint begin, TimePoint end, const PropertyValue &value); - void cleanup(TimePoint now); + void add(ClassID class_id, const TimePoint& begin, const TimePoint& end, const PropertyValue &value); + void cleanup(const TimePoint& now); bool hasTransitions() const; bool empty() const; }; diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 4e0c41185..415e34246 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -86,13 +86,13 @@ void Style::update(const TransformState& transform, } } -void Style::cascade(const std::vector& classes, TimePoint now) { +void Style::cascade(const std::vector& classes, const TimePoint& now) { for (const auto& layer : layers) { layer->setClasses(classes, now, defaultTransition); } } -void Style::recalculate(float z, TimePoint now) { +void Style::recalculate(float z, const TimePoint& now) { uv::writelock lock(mtx); for (const auto& source : sources) { diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 850c06659..16e0afcd4 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -54,8 +54,8 @@ public: // a tile is ready so observers can render the tile. void update(const TransformState&, TexturePool&); - void cascade(const std::vector&, TimePoint now); - void recalculate(float z, TimePoint now); + void cascade(const std::vector&, const TimePoint& now); + void recalculate(float z, const TimePoint& now); void setDefaultTransitionDuration(Duration); bool hasTransitions() const; diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp index 7f9c7ecbf..ad96c38c3 100644 --- a/src/mbgl/style/style_layer.cpp +++ b/src/mbgl/style/style_layer.cpp @@ -28,7 +28,7 @@ bool StyleLayer::isVisible() const { } } -void StyleLayer::setClasses(const std::vector &class_names, const TimePoint now, +void StyleLayer::setClasses(const std::vector &class_names, const TimePoint& now, const PropertyTransition &defaultTransition) { // Stores all keys that we have already added transitions for. std::set already_applied; @@ -69,7 +69,7 @@ void StyleLayer::setClasses(const std::vector &class_names, const T // Helper function for applying all properties of a a single class that haven't been applied yet. void StyleLayer::applyClassProperties(const ClassID class_id, - std::set &already_applied, TimePoint now, + std::set &already_applied, const TimePoint& now, const PropertyTransition &defaultTransition) { auto style_it = styles.find(class_id); if (style_it == styles.end()) { @@ -134,7 +134,7 @@ private: }; template -void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { auto it = appliedStyle.find(key); if (it != appliedStyle.end()) { AppliedClassProperties &applied = it->second; @@ -152,7 +152,7 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c } template -void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { auto it = appliedStyle.find(key); if (it != appliedStyle.end()) { AppliedClassProperties &applied = it->second; @@ -174,7 +174,7 @@ void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, cons } template <> -void StyleLayer::applyStyleProperties(const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { properties.set(); FillProperties &fill = properties.get(); applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now, zoomHistory); @@ -187,7 +187,7 @@ void StyleLayer::applyStyleProperties(const float z, const TimeP } template <> -void StyleLayer::applyStyleProperties(const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { properties.set(); LineProperties &line = properties.get(); applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now, zoomHistory); @@ -201,11 +201,11 @@ void StyleLayer::applyStyleProperties(const float z, const TimeP applyStyleProperty(PropertyKey::LineImage, line.image, z, now, zoomHistory); // for scaling dasharrays - applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), TimePoint::max(), zoomHistory); + applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), now, zoomHistory); } template <> -void StyleLayer::applyStyleProperties(const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { properties.set(); SymbolProperties &symbol = properties.get(); applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now, zoomHistory); @@ -228,7 +228,7 @@ void StyleLayer::applyStyleProperties(const float z, const Tim } template <> -void StyleLayer::applyStyleProperties(const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { properties.set(); RasterProperties &raster = properties.get(); applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now, zoomHistory); @@ -241,7 +241,7 @@ void StyleLayer::applyStyleProperties(const float z, const Tim } template <> -void StyleLayer::applyStyleProperties(const float z, const TimePoint now, const ZoomHistory &zoomHistory) { +void StyleLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) { properties.set(); BackgroundProperties &background = properties.get(); applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now, zoomHistory); @@ -249,7 +249,7 @@ void StyleLayer::applyStyleProperties(const float z, const applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now, zoomHistory); } -void StyleLayer::updateProperties(float z, const TimePoint now, ZoomHistory &zoomHistory) { +void StyleLayer::updateProperties(float z, const TimePoint& now, ZoomHistory &zoomHistory) { cleanupAppliedStyleProperties(now); switch (type) { @@ -271,7 +271,7 @@ bool StyleLayer::hasTransitions() const { return false; } -void StyleLayer::cleanupAppliedStyleProperties(TimePoint now) { +void StyleLayer::cleanupAppliedStyleProperties(const TimePoint& now) { for (auto it = appliedStyle.begin(); it != appliedStyle.end();) { AppliedClassProperties& appliedPropertyValues = it->second; appliedPropertyValues.cleanup(now); diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp index 774ed3901..97bd479b2 100644 --- a/src/mbgl/style/style_layer.hpp +++ b/src/mbgl/style/style_layer.hpp @@ -40,10 +40,10 @@ public: // Updates the StyleProperties information in this layer by evaluating all // pending transitions and applied classes in order. - void updateProperties(float z, TimePoint now, ZoomHistory &zoomHistory); + void updateProperties(float z, const TimePoint& now, ZoomHistory &zoomHistory); // Sets the list of classes and creates transitions to the currently applied values. - void setClasses(const std::vector &class_names, TimePoint now, + void setClasses(const std::vector &class_names, const TimePoint& now, const PropertyTransition &defaultTransition); bool hasTransitions() const; @@ -51,16 +51,16 @@ public: private: // Applies all properties from a class, if they haven't been applied already. void applyClassProperties(ClassID class_id, std::set &already_applied, - TimePoint now, const PropertyTransition &defaultTransition); + const TimePoint& now, const PropertyTransition &defaultTransition); // Sets the properties of this object by evaluating all pending transitions and // aplied classes in order. - template void applyStyleProperties(float z, TimePoint now, const ZoomHistory &zoomHistory); - template void applyStyleProperty(PropertyKey key, T &, float z, TimePoint now, const ZoomHistory &zoomHistory); - template void applyTransitionedStyleProperty(PropertyKey key, T &, float z, TimePoint now, const ZoomHistory &zoomHistory); + template void applyStyleProperties(float z, const TimePoint& now, const ZoomHistory &zoomHistory); + template void applyStyleProperty(PropertyKey key, T &, float z, const TimePoint& now, const ZoomHistory &zoomHistory); + template void applyTransitionedStyleProperty(PropertyKey key, T &, float z, const TimePoint& now, const ZoomHistory &zoomHistory); // Removes all expired style transitions. - void cleanupAppliedStyleProperties(TimePoint now); + void cleanupAppliedStyleProperties(const TimePoint& now); public: // The name of this layer. diff --git a/src/mbgl/style/zoom_history.hpp b/src/mbgl/style/zoom_history.hpp index 2debff8d4..9eb76e5ec 100644 --- a/src/mbgl/style/zoom_history.hpp +++ b/src/mbgl/style/zoom_history.hpp @@ -13,12 +13,12 @@ struct ZoomHistory { TimePoint lastIntegerZoomTime; bool first = true; - void update(float z, TimePoint now) { + void update(float z, const TimePoint& now) { if (first) { first = false; lastIntegerZoom = std::floor(z); - lastIntegerZoomTime = TimePoint(Duration(0)); + lastIntegerZoomTime = TimePoint(Duration::zero()); lastZoom = z; } diff --git a/src/mbgl/util/transition.cpp b/src/mbgl/util/transition.cpp index 55de25f0c..bab5e12fd 100644 --- a/src/mbgl/util/transition.cpp +++ b/src/mbgl/util/transition.cpp @@ -10,7 +10,7 @@ UnitBezier ease(0, 0, 0.25, 1); transition::~transition() {} template -transition::state ease_transition::update(TimePoint now) const { +transition::state ease_transition::update(const TimePoint& now) const { float t = progress(now); if (t >= 1) { value = to; diff --git a/src/mbgl/util/transition.hpp b/src/mbgl/util/transition.hpp index de9fffb66..5cfbc0a7c 100644 --- a/src/mbgl/util/transition.hpp +++ b/src/mbgl/util/transition.hpp @@ -14,18 +14,18 @@ public: complete }; - inline transition(TimePoint start_, Duration duration_) + inline transition(const TimePoint& start_, const Duration& duration_) : start(start_), duration(duration_) {} - inline float progress(TimePoint now) const { + inline float progress(const TimePoint& now) const { if (duration == Duration::zero()) return 1; if (start > now) return 0; return std::chrono::duration(now - start) / duration; } - virtual state update(TimePoint now) const = 0; + virtual state update(const TimePoint& now) const = 0; virtual ~transition(); protected: @@ -36,13 +36,13 @@ protected: template class ease_transition : public transition { public: - ease_transition(T from_, T to_, T& value_, TimePoint start_, Duration duration_) + ease_transition(T from_, T to_, T& value_, const TimePoint& start_, const Duration& duration_) : transition(start_, duration_), from(from_), to(to_), value(value_) {} - state update(TimePoint now) const; + state update(const TimePoint& now) const; private: const T from, to; @@ -53,12 +53,12 @@ private: template class timeout : public transition { public: - timeout(T final_value_, T& value_, TimePoint start_, Duration duration_) + timeout(T final_value_, T& value_, const TimePoint& start_, const Duration& duration_) : transition(start_, duration_), final_value(final_value_), value(value_) {} - state update(TimePoint now) const { + state update(const TimePoint& now) const { if (progress(now) >= 1) { value = final_value; return complete; From 0ea8a37cb081302707c7815f3df5745bd3d6eef3 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 14 Jul 2015 15:14:39 +0300 Subject: [PATCH 30/41] Unify default transition values in MapData Relevant changes: - Added 'defaultFadeDuration' and 'defaultTransitionDelay' to MapData; - Painter & StyleParser now receives a reference to MapData; - As previously seen on the code: 300ms is the default fade duration and 0ms is the default transition duration; - We no longer pass the current time point to Style, since it now uses MapData.animationTime, which gets updated in MapContext::update(). - Updated StyleParser check to use a mock MapData; --- src/mbgl/map/map_context.cpp | 14 +++------ src/mbgl/map/map_data.hpp | 28 +++++++++++++++-- src/mbgl/renderer/painter.cpp | 5 ++-- src/mbgl/renderer/painter.hpp | 4 +-- src/mbgl/renderer/painter_debug.cpp | 7 +++-- src/mbgl/renderer/painter_line.cpp | 11 +++---- src/mbgl/renderer/painter_symbol.cpp | 5 ++-- .../style/piecewisefunction_properties.hpp | 1 - src/mbgl/style/property_transition.hpp | 2 ++ src/mbgl/style/style.cpp | 19 ++++++------ src/mbgl/style/style.hpp | 6 ++-- src/mbgl/style/style_parser.cpp | 30 ++++++++++--------- src/mbgl/style/style_parser.hpp | 5 +++- test/miscellaneous/style_parser.cpp | 9 +++++- 14 files changed, 88 insertions(+), 58 deletions(-) diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 7f2fe4e98..23bb5f590 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -254,21 +254,15 @@ void MapContext::update() { return; } - const TimePoint now = Clock::now(); - - data.setAnimationTime(now); - - if (updated & static_cast(Update::DefaultTransitionDuration)) { - style->setDefaultTransitionDuration(data.getDefaultTransitionDuration()); - } + data.setAnimationTime(Clock::now()); if (updated & static_cast(Update::Classes)) { - style->cascade(data.getClasses(), now); + style->cascade(); } if (updated & static_cast(Update::Classes) || updated & static_cast(Update::Zoom)) { - style->recalculate(transformState.getNormalizedZoom(), now); + style->recalculate(transformState.getNormalizedZoom()); } style->update(transformState, *texturePool); @@ -330,7 +324,7 @@ MapContext::RenderResult MapContext::renderSync(const TransformState& state, con glObjectStore.performCleanup(); if (!painter) { - painter = std::make_unique(data.pixelRatio); + painter = std::make_unique(data); painter->setup(); } diff --git a/src/mbgl/map/map_data.hpp b/src/mbgl/map/map_data.hpp index 1703aff8c..aadc8dcd6 100644 --- a/src/mbgl/map/map_data.hpp +++ b/src/mbgl/map/map_data.hpp @@ -20,10 +20,14 @@ class MapData { using Lock = std::lock_guard; public: - inline MapData(MapMode mode_, const float pixelRatio_) : mode(mode_), pixelRatio(pixelRatio_) { + inline MapData(MapMode mode_, const float pixelRatio_) + : mode(mode_) + , pixelRatio(pixelRatio_) + , animationTime(Duration::zero()) + , defaultFadeDuration(std::chrono::milliseconds(300)) + , defaultTransitionDuration(Duration::zero()) + , defaultTransitionDelay(Duration::zero()) { assert(pixelRatio > 0); - setAnimationTime(TimePoint::min()); - setDefaultTransitionDuration(Duration::zero()); } // Adds the class if it's not yet set. Returns true when it added the class, and false when it @@ -73,6 +77,14 @@ public: animationTime = timePoint.time_since_epoch(); }; + inline Duration getDefaultFadeDuration() const { + return defaultFadeDuration; + } + + inline void setDefaultFadeDuration(const Duration& duration) { + defaultFadeDuration = duration; + } + inline Duration getDefaultTransitionDuration() const { return defaultTransitionDuration; } @@ -81,6 +93,14 @@ public: defaultTransitionDuration = duration; } + inline Duration getDefaultTransitionDelay() const { + return defaultTransitionDelay; + } + + inline void setDefaultTransitionDelay(const Duration& delay) { + defaultTransitionDelay = delay; + } + util::exclusive getAnnotationManager() { return util::exclusive( &annotationManager, @@ -101,7 +121,9 @@ private: std::atomic debug { false }; std::atomic collisionDebug { false }; std::atomic animationTime; + std::atomic defaultFadeDuration; std::atomic defaultTransitionDuration; + std::atomic defaultTransitionDelay; // TODO: make private public: diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 77ee868c3..7570b6a74 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -41,14 +42,14 @@ using namespace mbgl; -Painter::Painter(const float pixelRatio_) : pixelRatio(pixelRatio_) { +Painter::Painter(MapData& data_) : data(data_) { } Painter::~Painter() { } bool Painter::needsAnimation() const { - return frameHistory.needsAnimation(std::chrono::milliseconds(300)); + return frameHistory.needsAnimation(data.getDefaultFadeDuration()) || state.isChanging(); } void Painter::setup() { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 3719b7f2a..869aaa49c 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -81,7 +81,7 @@ struct RenderItem { class Painter : private util::noncopyable { public: - Painter(float pixelRatio); + Painter(MapData& data); ~Painter(); void setup(); @@ -191,7 +191,7 @@ public: }(); private: - const float pixelRatio; + MapData& data; TransformState state; FrameData frame; diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp index b5d9e343e..aa3fcba5d 100644 --- a/src/mbgl/renderer/painter_debug.cpp +++ b/src/mbgl/renderer/painter_debug.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) { // Draw white outline plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }}; - lineWidth(4.0f * pixelRatio); + lineWidth(4.0f * data.pixelRatio); bucket.drawLines(*plainShader); #ifndef GL_ES_VERSION_2_0 @@ -39,7 +40,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) { // Draw black text. plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }}; - lineWidth(2.0f * pixelRatio); + lineWidth(2.0f * data.pixelRatio); bucket.drawLines(*plainShader); config.depthTest = true; @@ -60,6 +61,6 @@ void Painter::renderDebugFrame(const mat4 &matrix) { // draw tile outline tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0)); plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }}; - lineWidth(4.0f * pixelRatio); + lineWidth(4.0f * data.pixelRatio); MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index())); } diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index 5f5a89d41..1ef921410 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const // the distance over which the line edge fades out. // Retina devices need a smaller distance to avoid aliasing. - float antialiasing = 1.0 / pixelRatio; + float antialiasing = 1.0 / data.pixelRatio; float blur = properties.blur + antialiasing; float edgeWidth = properties.width / 2.0; @@ -61,7 +62,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linesdfShader->u_matrix = vtxMatrix; linesdfShader->u_exmatrix = extrudeMatrix; linesdfShader->u_linewidth = {{ outset, inset }}; - linesdfShader->u_ratio = pixelRatio; + linesdfShader->u_ratio = data.pixelRatio; linesdfShader->u_blur = blur; linesdfShader->u_color = color; @@ -80,7 +81,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }}; linesdfShader->u_tex_y_b = posB.y; linesdfShader->u_image = 0; - linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * pixelRatio) / 2; + linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * data.pixelRatio) / 2; linesdfShader->u_mix = properties.dash_array.t; bucket.drawLineSDF(*linesdfShader); @@ -96,7 +97,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const linepatternShader->u_matrix = vtxMatrix; linepatternShader->u_exmatrix = extrudeMatrix; linepatternShader->u_linewidth = {{ outset, inset }}; - linepatternShader->u_ratio = pixelRatio; + linepatternShader->u_ratio = data.pixelRatio; linepatternShader->u_blur = blur; linepatternShader->u_pattern_size_a = {{imagePosA.size[0] * factor * properties.image.fromScale, imagePosA.size[1]}}; @@ -120,7 +121,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const lineShader->u_matrix = vtxMatrix; lineShader->u_exmatrix = extrudeMatrix; lineShader->u_linewidth = {{ outset, inset }}; - lineShader->u_ratio = pixelRatio; + lineShader->u_ratio = data.pixelRatio; lineShader->u_blur = blur; lineShader->u_color = color; diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index d0757d629..6d12768e2 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ void Painter::renderSDF(SymbolBucket &bucket, sdfShader.u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level - FadeProperties f = frameHistory.getFadeProperties(std::chrono::milliseconds(300)); + FadeProperties f = frameHistory.getFadeProperties(data.getDefaultFadeDuration()); sdfShader.u_fadedist = f.fadedist * 10; sdfShader.u_minfadezoom = std::floor(f.minfadezoom * 10); sdfShader.u_maxfadezoom = std::floor(f.maxfadezoom * 10); @@ -60,7 +61,7 @@ void Painter::renderSDF(SymbolBucket &bucket, // The default gamma value has to be adjust for the current pixelratio so that we're not // drawing blurry font on retina screens. - const float gamma = 0.105 * sdfFontSize / fontSize / pixelRatio; + const float gamma = 0.105 * sdfFontSize / fontSize / data.pixelRatio; const float sdfPx = 8.0f; const float blurOffset = 1.19f; diff --git a/src/mbgl/style/piecewisefunction_properties.hpp b/src/mbgl/style/piecewisefunction_properties.hpp index 0440655ba..f05ee6864 100644 --- a/src/mbgl/style/piecewisefunction_properties.hpp +++ b/src/mbgl/style/piecewisefunction_properties.hpp @@ -11,7 +11,6 @@ template struct PiecewiseConstantFunction { inline PiecewiseConstantFunction(const std::vector> &values_, std::chrono::duration duration_) : values(values_), duration(duration_) {} inline PiecewiseConstantFunction(T &value, std::chrono::duration duration_) : values({{ 0, value }}), duration(duration_) {} - inline PiecewiseConstantFunction() : values(), duration(std::chrono::milliseconds(300)) {} T evaluate(float z, const ZoomHistory &zoomHistory) const; private: diff --git a/src/mbgl/style/property_transition.hpp b/src/mbgl/style/property_transition.hpp index 584d67db5..4515fdc92 100644 --- a/src/mbgl/style/property_transition.hpp +++ b/src/mbgl/style/property_transition.hpp @@ -8,6 +8,8 @@ namespace mbgl { struct PropertyTransition { + explicit inline PropertyTransition(const Duration& duration_, const Duration& delay_) + : duration(duration_), delay(delay_) {} Duration duration = Duration::zero(); Duration delay = Duration::zero(); }; diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 415e34246..994592408 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ void Style::setJSON(const std::string& json, const std::string&) { return; } - StyleParser parser; + StyleParser parser(data); parser.parse(doc); sources = parser.getSources(); @@ -86,23 +87,25 @@ void Style::update(const TransformState& transform, } } -void Style::cascade(const std::vector& classes, const TimePoint& now) { +void Style::cascade() { for (const auto& layer : layers) { - layer->setClasses(classes, now, defaultTransition); + layer->setClasses(data.getClasses(), + data.getAnimationTime(), + PropertyTransition { data.getDefaultTransitionDuration(), data.getDefaultTransitionDelay() }); } } -void Style::recalculate(float z, const TimePoint& now) { +void Style::recalculate(float z) { uv::writelock lock(mtx); for (const auto& source : sources) { source->enabled = false; } - zoomHistory.update(z, now); + zoomHistory.update(z, data.getAnimationTime()); for (const auto& layer : layers) { - layer->updateProperties(z, now, zoomHistory); + layer->updateProperties(z, data.getAnimationTime(), zoomHistory); if (!layer->bucket) { continue; } @@ -124,10 +127,6 @@ Source* Style::getSource(const std::string& id) const { return it != sources.end() ? it->get() : nullptr; } -void Style::setDefaultTransitionDuration(Duration duration) { - defaultTransition.duration = duration; -} - bool Style::hasTransitions() const { for (const auto& layer : layers) { if (layer->hasTransitions()) { diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 16e0afcd4..6d8a7ae52 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -54,10 +54,9 @@ public: // a tile is ready so observers can render the tile. void update(const TransformState&, TexturePool&); - void cascade(const std::vector&, const TimePoint& now); - void recalculate(float z, const TimePoint& now); + void cascade(); + void recalculate(float z); - void setDefaultTransitionDuration(Duration); bool hasTransitions() const; std::exception_ptr getLastError() const { @@ -101,7 +100,6 @@ private: std::exception_ptr lastError; - PropertyTransition defaultTransition; std::unique_ptr mtx; ZoomHistory zoomHistory; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index 53313a548..4767bdafa 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -21,7 +22,8 @@ namespace mbgl { using JSVal = const rapidjson::Value&; -StyleParser::StyleParser() { +StyleParser::StyleParser(MapData& data_) + : data(data_) { } void StyleParser::parse(JSVal document) { @@ -399,13 +401,13 @@ template StyleParser::Result> StyleParser::parsePiecewiseConstantFunction(JSVal value, Duration duration) { if (!value.HasMember("stops")) { Log::Warning(Event::ParseStyle, "function must specify a function type"); - return Result> { StyleParserFailure, {} }; + return Result> { StyleParserFailure, { {}, duration } }; } auto stops = parseStops(value["stops"], ""); if (!std::get<0>(stops)) { - return Result> { StyleParserFailure, {} }; + return Result> { StyleParserFailure, { {}, duration } }; } return Result> { StyleParserSuccess, { std::get<1>(stops), duration } }; @@ -578,20 +580,21 @@ template<> StyleParser::Result StyleParser::parseProperty } template<> StyleParser::Result StyleParser::parseProperty(JSVal value, const char */*property_name*/) { - PropertyTransition transition; + PropertyTransition transition { data.getDefaultTransitionDuration(), data.getDefaultTransitionDelay() }; if (value.IsObject()) { + bool parsed = false; if (value.HasMember("duration") && value["duration"].IsNumber()) { transition.duration = std::chrono::milliseconds(value["duration"].GetUint()); + parsed = true; } if (value.HasMember("delay") && value["delay"].IsNumber()) { transition.delay = std::chrono::milliseconds(value["delay"].GetUint()); + parsed = true; + } + if (!parsed) { + return Result { StyleParserFailure, std::move(transition) }; } } - - if (transition.duration == Duration::zero() && transition.delay == Duration::zero()) { - return Result { StyleParserFailure, std::move(transition) }; - } - return Result { StyleParserSuccess, std::move(transition) }; } @@ -653,7 +656,7 @@ template<> StyleParser::Result> StyleParser::parseProperty(JSVal } template<> StyleParser::Result>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) { - Duration duration = std::chrono::milliseconds(300); + Duration duration = data.getDefaultFadeDuration(); if (transition.HasMember("duration")) { duration = std::chrono::milliseconds(transition["duration"].GetUint()); } @@ -667,13 +670,12 @@ template<> StyleParser::Result>>> { std::get<0>(floatarray), { parsed, duration } }; } else { Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name); - return Result>>> { StyleParserFailure, {} }; + return Result>>> { StyleParserFailure, { {}, duration } }; } } template<> StyleParser::Result>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) { - - Duration duration = std::chrono::milliseconds(300); + Duration duration = data.getDefaultFadeDuration(); if (transition.HasMember("duration")) { duration = std::chrono::milliseconds(transition["duration"].GetUint()); } @@ -686,7 +688,7 @@ template<> StyleParser::Result>> St return Result>> { StyleParserSuccess, { parsed, duration } }; } else { Log::Warning(Event::ParseStyle, "value of '%s' must be string or a string function", property_name); - return Result>> { StyleParserFailure, {} }; + return Result>> { StyleParserFailure, { {}, duration } }; } } diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index 2daa5e14d..5f0c509eb 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -31,7 +31,7 @@ public: template using Result = std::pair; - StyleParser(); + StyleParser(MapData& data); void parse(JSVal document); @@ -117,6 +117,9 @@ private: // URL template for glyph PBFs. std::string glyph_url; + + // Obtain default transition duration from map data. + MapData& data; }; } diff --git a/test/miscellaneous/style_parser.cpp b/test/miscellaneous/style_parser.cpp index 7a38ba054..e88d79841 100644 --- a/test/miscellaneous/style_parser.cpp +++ b/test/miscellaneous/style_parser.cpp @@ -3,6 +3,9 @@ #include #include +#include +#include + #include #include "../fixtures/fixture_log_observer.hpp" @@ -35,7 +38,11 @@ TEST_P(StyleParserTest, ParseStyle) { FixtureLogObserver* observer = new FixtureLogObserver(); Log::setObserver(std::unique_ptr(observer)); - StyleParser parser; + MapMode mapMode = MapMode::Continuous; + const float pixelRatio = 1.0f; + + MapData data(mapMode, pixelRatio); + StyleParser parser(data); parser.parse(styleDoc); for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) { From bef3e1590b38217d71cb519b2304d52efa5885fe Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 14 Jul 2015 18:12:48 +0300 Subject: [PATCH 31/41] Force style cascade in MapContext::loadStyleJSON Fixes #1889. --- src/mbgl/map/map_context.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 23bb5f590..61614dd0e 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -133,6 +133,9 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base) style->setJSON(json, base); style->setObserver(this); + // force style cascade, causing all pending transitions to complete. + style->cascade(); + updated |= static_cast(Update::DefaultTransitionDuration); updated |= static_cast(Update::Classes); updated |= static_cast(Update::Zoom); From 38d8d1820d507f3bf15d7de0e37c6f3a5fbbba77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 14 Jul 2015 10:55:36 -0700 Subject: [PATCH 32/41] Bumped podspec to 0.5.2 with symbols --- ios/MapboxGL.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/MapboxGL.podspec b/ios/MapboxGL.podspec index a49fb7deb..9795c44ad 100644 --- a/ios/MapboxGL.podspec +++ b/ios/MapboxGL.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'MapboxGL' - m.version = '0.5.1' + m.version = '0.5.2-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.' From 3c1d46113effef75c44a28a1847cbac4d1003948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 14 Jul 2015 11:29:02 -0700 Subject: [PATCH 33/41] [publish ios-v0.5.2] From 70aea89e131125b3d92fcc99c5b3ecd1e148d0c8 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 7 Jul 2015 20:23:43 +0300 Subject: [PATCH 34/41] Add an interface for invoking cancellable tasks on the RunLoop This is interface is going to be used the WorkQueue in the following patches. --- src/mbgl/util/run_loop.cpp | 2 +- src/mbgl/util/run_loop.hpp | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/mbgl/util/run_loop.cpp b/src/mbgl/util/run_loop.cpp index 7f277c988..5c9595946 100644 --- a/src/mbgl/util/run_loop.cpp +++ b/src/mbgl/util/run_loop.cpp @@ -15,7 +15,7 @@ RunLoop::~RunLoop() { } void RunLoop::withMutex(std::function&& fn) { - std::lock_guard lock(mutex); + std::lock_guard lock(mutex); fn(); } diff --git a/src/mbgl/util/run_loop.hpp b/src/mbgl/util/run_loop.hpp index 2175ea977..7f56c18dc 100644 --- a/src/mbgl/util/run_loop.hpp +++ b/src/mbgl/util/run_loop.hpp @@ -19,6 +19,10 @@ public: RunLoop(uv_loop_t*); ~RunLoop(); + static RunLoop* Get() { + return current.get(); + } + static uv_loop_t* getLoop() { return current.get()->get(); } @@ -37,6 +41,25 @@ public: async.send(); } + // Post the cancellable work fn(args...) to this RunLoop. + template + std::unique_ptr + invokeCancellable(Fn&& fn, Args&&... args) { + auto flag = std::make_shared(); + *flag = false; + + auto tuple = std::make_tuple(std::move(args)...); + auto task = std::make_shared>( + std::move(fn), + std::move(tuple), + flag); + + withMutex([&] { queue.push(task); }); + async.send(); + + return std::make_unique(task); + } + // Invoke fn(args...) on this RunLoop, then invoke callback(results...) on the current RunLoop. template std::unique_ptr @@ -85,7 +108,7 @@ private: void operator()() override { // Lock the mutex while processing so that cancel() will block. - std::lock_guard lock(mutex); + std::lock_guard lock(mutex); if (!canceled || !*canceled) { invoke(std::make_index_sequence::value>{}); } @@ -100,7 +123,7 @@ private: // If the task has completed and the after callback has executed, this will // do nothing. void cancel() override { - std::lock_guard lock(mutex); + std::lock_guard lock(mutex); *canceled = true; } @@ -110,7 +133,7 @@ private: func(std::get(std::forward

(params))...); } - std::mutex mutex; + std::recursive_mutex mutex; std::shared_ptr canceled; F func; @@ -123,7 +146,7 @@ private: void process(); Queue queue; - std::mutex mutex; + std::recursive_mutex mutex; uv::async async; static uv::tls current; From 7d500e9330eaf096fdbe89e33b1bf00526873e0e Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 14 Jul 2015 17:01:20 +0300 Subject: [PATCH 35/41] Introduce the WorkQueue The WorkQueue allow other threads to submit tasks to be executed in the thread that the WorkQueue lives on. The WorkQueue will cancel all the pending tasks when it gets destructed, to make sure the tasks won't get called with invalid references. --- src/mbgl/util/work_queue.cpp | 37 ++++++++++++++++++++++++++++++++++++ src/mbgl/util/work_queue.hpp | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/mbgl/util/work_queue.cpp create mode 100644 src/mbgl/util/work_queue.hpp diff --git a/src/mbgl/util/work_queue.cpp b/src/mbgl/util/work_queue.cpp new file mode 100644 index 000000000..7e1406bba --- /dev/null +++ b/src/mbgl/util/work_queue.cpp @@ -0,0 +1,37 @@ +#include + +#include + +namespace mbgl { +namespace util { + +WorkQueue::WorkQueue() : runLoop(RunLoop::Get()) { +} + +WorkQueue::~WorkQueue() { + assert(runLoop == RunLoop::Get()); + + // Cancel all pending WorkRequests. + while (!queue.empty()) { + queue.pop(); + } +} + +void WorkQueue::push(std::function&& fn) { + std::lock_guard lock(queueMutex); + + auto workRequest = runLoop->invokeCancellable(std::bind(&WorkQueue::pop, this, std::move(fn))); + queue.push(std::move(workRequest)); +} + +void WorkQueue::pop(const std::function& fn) { + assert(runLoop == RunLoop::Get()); + + fn(); + + std::lock_guard lock(queueMutex); + queue.pop(); +} + +} +} diff --git a/src/mbgl/util/work_queue.hpp b/src/mbgl/util/work_queue.hpp new file mode 100644 index 000000000..dcec5668b --- /dev/null +++ b/src/mbgl/util/work_queue.hpp @@ -0,0 +1,36 @@ +#ifndef MBGL_UTIL_WORK_QUEUE +#define MBGL_UTIL_WORK_QUEUE + +#include +#include + +#include +#include +#include +#include + +namespace mbgl { +namespace util { + +class RunLoop; + +class WorkQueue : private util::noncopyable { +public: + WorkQueue(); + virtual ~WorkQueue(); + + void push(std::function&&); + +private: + void pop(const std::function&); + + std::queue> queue; + std::mutex queueMutex; + + RunLoop* runLoop; +}; + +} +} + +#endif From 7d4349e308a4ff2c90feda2d9ddd348f7a2621ae Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Wed, 15 Jul 2015 18:21:37 +0300 Subject: [PATCH 36/41] Added unit tests for the WorkQueue --- test/miscellaneous/work_queue.cpp | 63 +++++++++++++++++++++++++++++++ test/test.gypi | 1 + 2 files changed, 64 insertions(+) create mode 100644 test/miscellaneous/work_queue.cpp diff --git a/test/miscellaneous/work_queue.cpp b/test/miscellaneous/work_queue.cpp new file mode 100644 index 000000000..a5f616fe5 --- /dev/null +++ b/test/miscellaneous/work_queue.cpp @@ -0,0 +1,63 @@ +#include "../fixtures/util.hpp" + +#include +#include +#include + +#include + +using namespace mbgl::util; + +class TestThread { +public: + TestThread(WorkQueue* queue_) : queue(queue_) {} + + void send(std::function&& fn) { + EXPECT_TRUE(ThreadContext::currentlyOn(ThreadType::Map)); + + queue->push(std::move(fn)); + } + +private: + WorkQueue* queue; +}; + +TEST(WorkQueue, push) { + RunLoop loop(uv_default_loop()); + + WorkQueue queue; + Thread thread({"Test", ThreadType::Map, ThreadPriority::Regular}, &queue); + + uint8_t count = 0; + + auto endTest = [&]() { + EXPECT_TRUE(ThreadContext::currentlyOn(ThreadType::Main)); + + if (++count == 4) { + loop.stop(); + } + }; + + thread.invoke(&TestThread::send, endTest); + thread.invoke(&TestThread::send, endTest); + thread.invoke(&TestThread::send, endTest); + thread.invoke(&TestThread::send, endTest); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); +} + +TEST(WorkQueue, cancel) { + RunLoop loop(uv_default_loop()); + + WorkQueue queue; + + auto work = [&]() { + FAIL() << "Should never be called"; + }; + + queue.push(work); + queue.push(work); + queue.push(work); + queue.push(work); + queue.push(work); +} diff --git a/test/test.gypi b/test/test.gypi index 461719e33..7d97290c8 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -69,6 +69,7 @@ 'miscellaneous/thread.cpp', 'miscellaneous/tile.cpp', 'miscellaneous/transform.cpp', + 'miscellaneous/work_queue.cpp', 'miscellaneous/variant.cpp', 'storage/storage.hpp', From c6e58515fcd83a49d8633dc769e1ad1e69074653 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Wed, 15 Jul 2015 16:10:09 +0300 Subject: [PATCH 37/41] Keep updating until all the tiles are State::parsed This is needed because of a race that can occur now that we requests Glyphs from the Map Thread: The glyph might arrive at the moment a tile is being parsed and they won't be notified again of any new data, remaining forever at the partial state. --- src/mbgl/map/source.cpp | 10 ++-------- src/mbgl/map/tile_worker.cpp | 5 ----- src/mbgl/map/tile_worker.hpp | 1 - src/mbgl/map/vector_tile_data.cpp | 4 ---- src/mbgl/map/vector_tile_data.hpp | 1 - 5 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 4ca64747b..a7ebf300f 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -240,14 +240,8 @@ bool Source::handlePartialTile(const TileID& id, Worker&) { return true; } - // The signal is only emitted if there was an actual change on the tile. The - // tile can be in a "partial" state waiting for resources and get reparsed on - // the arrival of new resources that were needed by another tile. - size_t bucketCount = data->countBuckets(); - return data->reparse([this, data, bucketCount]() { - if (data->countBuckets() > bucketCount) { - emitTileLoaded(false); - } + return data->reparse([this, data]() { + emitTileLoaded(false); }); } diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp index 15183c0e4..dd56f33f5 100644 --- a/src/mbgl/map/tile_worker.cpp +++ b/src/mbgl/map/tile_worker.cpp @@ -44,11 +44,6 @@ Bucket* TileWorker::getBucket(const StyleLayer& layer) const { return it->second.get(); } -size_t TileWorker::countBuckets() const { - std::lock_guard lock(bucketsMutex); - return buckets.size(); -} - TileParseResult TileWorker::parse(const GeometryTile& geometryTile) { partialParse = false; diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/map/tile_worker.hpp index 2306bf1ac..da5c76650 100644 --- a/src/mbgl/map/tile_worker.hpp +++ b/src/mbgl/map/tile_worker.hpp @@ -41,7 +41,6 @@ public: ~TileWorker(); Bucket* getBucket(const StyleLayer&) const; - size_t countBuckets() const; TileParseResult parse(const GeometryTile&); void redoPlacement(float angle, bool collisionDebug); diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index 57b42aaaf..c9ee33910 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -98,10 +98,6 @@ Bucket* VectorTileData::getBucket(const StyleLayer& layer) { return tileWorker.getBucket(layer); } -size_t VectorTileData::countBuckets() const { - return tileWorker.countBuckets(); -} - void VectorTileData::redoPlacement(float angle, bool collisionDebug) { if (angle == currentAngle && collisionDebug == currentCollisionDebug) return; diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 3b73ded0c..e0e8be29b 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -23,7 +23,6 @@ public: ~VectorTileData(); Bucket* getBucket(const StyleLayer&) override; - size_t countBuckets() const; void request(float pixelRatio, const std::function& callback); From a75cc8c06b8d931b3b85dd9ac6d852f84b06e5b2 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Thu, 9 Jul 2015 11:26:45 +0300 Subject: [PATCH 38/41] Make Glyph requests from the Map Thread Now the requests are bound to the Map Thread loop and we can cancel it quickly when shutting down or changing style. Previously requests were made by the workers and we would have to wait them to finish because workers are destroyed before the GlyphStore. This was giving the impression that the application was frozen (in fact it was, momentarily). --- src/mbgl/renderer/symbol_bucket.cpp | 2 +- src/mbgl/style/style.cpp | 4 +- src/mbgl/text/glyph_store.cpp | 102 ++++++++++++++-------------- src/mbgl/text/glyph_store.hpp | 36 ++++------ 4 files changed, 68 insertions(+), 76 deletions(-) diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index cfa56c992..c99b725e7 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -160,7 +160,7 @@ bool SymbolBucket::needsDependencies(const GeometryTileLayer& layer, util::mergeLines(features); } - if (glyphStore.requestGlyphRangesIfNeeded(layout.text.font, ranges)) { + if (!glyphStore.hasGlyphRanges(layout.text.font, ranges)) { return true; } diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 994592408..5f92bb266 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -22,9 +22,9 @@ namespace mbgl { -Style::Style(MapData& data_, uv_loop_t* loop) +Style::Style(MapData& data_, uv_loop_t*) : data(data_), - glyphStore(std::make_unique(loop)), + glyphStore(std::make_unique()), glyphAtlas(std::make_unique(1024, 1024)), spriteStore(std::make_unique()), spriteAtlas(std::make_unique(512, 512, data.pixelRatio, *spriteStore)), diff --git a/src/mbgl/text/glyph_store.cpp b/src/mbgl/text/glyph_store.cpp index 0f507deb4..17c1524a8 100644 --- a/src/mbgl/text/glyph_store.cpp +++ b/src/mbgl/text/glyph_store.cpp @@ -1,95 +1,98 @@ #include -#include -#include +#include +#include #include -#include +#include namespace mbgl { -GlyphStore::GlyphStore(uv_loop_t* loop) - : asyncEmitGlyphRangeLoaded(std::make_unique(loop, [this] { emitGlyphRangeLoaded(); })), - asyncEmitGlyphRangeLoadedingFailed(std::make_unique(loop, [this] { emitGlyphRangeLoadingFailed(); })), - observer(nullptr) { - asyncEmitGlyphRangeLoaded->unref(); - asyncEmitGlyphRangeLoadedingFailed->unref(); +GlyphStore::GlyphStore() { } GlyphStore::~GlyphStore() { - observer = nullptr; } -void GlyphStore::setURL(const std::string &url) { - glyphURL = url; -} - -bool GlyphStore::requestGlyphRangesIfNeeded(const std::string& fontStackName, - const std::set& glyphRanges) { - bool requestIsNeeded = false; - - if (glyphRanges.empty()) { - return requestIsNeeded; - } +void GlyphStore::requestGlyphRange(const std::string& fontStackName, const GlyphRange& range) { + assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); auto successCallback = [this, fontStackName](GlyphPBF* glyph) { - auto fontStack = createFontStack(fontStackName); try { - glyph->parse(**fontStack); - asyncEmitGlyphRangeLoaded->send(); + { + auto fontStack = createFontStack(fontStackName); + glyph->parse(**fontStack); + } + emitGlyphRangeLoaded(); } catch (const std::exception&) { - std::lock_guard lock(errorMessageMutex); - errorMessage = "Failed to parse [" + glyph->getURL() + "]"; - asyncEmitGlyphRangeLoadedingFailed->send(); + std::string message = "Failed to parse [" + glyph->getURL() + "]"; + emitGlyphRangeLoadingFailed(message); } }; auto failureCallback = [this](const std::string& message) { - std::lock_guard lock(errorMessageMutex); - errorMessage = message; - asyncEmitGlyphRangeLoadedingFailed->send(); + emitGlyphRangeLoadingFailed(message); }; std::lock_guard lock(rangesMutex); auto& rangeSets = ranges[fontStackName]; + const auto& rangeSetsIt = rangeSets.find(range); + if (rangeSetsIt != rangeSets.end()) { + return; + } + + rangeSets.emplace(range, std::make_unique(glyphURL, fontStackName, range, + successCallback, failureCallback)); +} + + +bool GlyphStore::hasGlyphRanges(const std::string& fontStackName, const std::set& glyphRanges) { + if (glyphRanges.empty()) { + return true; + } + + std::lock_guard lock(rangesMutex); + const auto& rangeSets = ranges[fontStackName]; + + bool hasRanges = true; + for (const auto& range : glyphRanges) { - const auto& rangeSets_it = rangeSets.find(range); - if (rangeSets_it == rangeSets.end()) { - auto glyph = std::make_unique(glyphURL, fontStackName, range, - successCallback, failureCallback); - rangeSets.emplace(range, std::move(glyph)); - requestIsNeeded = true; + const auto& rangeSetsIt = rangeSets.find(range); + if (rangeSetsIt == rangeSets.end()) { + // Post the request to the Map thread. + workQueue.push(std::bind(&GlyphStore::requestGlyphRange, this, fontStackName, range)); + hasRanges = false; continue; } - if (!rangeSets_it->second->isParsed()) { - requestIsNeeded = true; + if (!rangeSetsIt->second->isParsed()) { + hasRanges = false; } } - return requestIsNeeded; + return hasRanges; } -util::exclusive GlyphStore::createFontStack(const std::string &fontStack) { +util::exclusive GlyphStore::createFontStack(const std::string& fontStack) { auto lock = std::make_unique>(stacksMutex); - auto stack_it = stacks.find(fontStack); - if (stack_it == stacks.end()) { - stack_it = stacks.emplace(fontStack, std::make_unique()).first; + auto it = stacks.find(fontStack); + if (it == stacks.end()) { + it = stacks.emplace(fontStack, std::make_unique()).first; } - return { stack_it->second.get(), std::move(lock) }; + return { it->second.get(), std::move(lock) }; } util::exclusive GlyphStore::getFontStack(const std::string &fontStack) { auto lock = std::make_unique>(stacksMutex); - const auto& stack_it = stacks.find(fontStack); - if (stack_it == stacks.end()) { + const auto& it = stacks.find(fontStack); + if (it == stacks.end()) { return { nullptr, nullptr }; } - return { stack_it->second.get(), std::move(lock) }; + return { it->second.get(), std::move(lock) }; } void GlyphStore::setObserver(Observer* observer_) { @@ -102,13 +105,12 @@ void GlyphStore::emitGlyphRangeLoaded() { } } -void GlyphStore::emitGlyphRangeLoadingFailed() { +void GlyphStore::emitGlyphRangeLoadingFailed(const std::string& message) { if (!observer) { return; } - std::lock_guard lock(errorMessageMutex); - auto error = std::make_exception_ptr(util::GlyphRangeLoadingException(errorMessage)); + auto error = std::make_exception_ptr(util::GlyphRangeLoadingException(message)); observer->onGlyphRangeLoadingFailed(error); } diff --git a/src/mbgl/text/glyph_store.hpp b/src/mbgl/text/glyph_store.hpp index a1f69b994..5d0f498c7 100644 --- a/src/mbgl/text/glyph_store.hpp +++ b/src/mbgl/text/glyph_store.hpp @@ -2,19 +2,14 @@ #define MBGL_TEXT_GLYPH_STORE #include - #include +#include +#include +#include #include #include #include -#include - -typedef struct uv_loop_s uv_loop_t; - -namespace uv { -class async; -} namespace mbgl { @@ -32,26 +27,25 @@ public: virtual void onGlyphRangeLoadingFailed(std::exception_ptr error) = 0; }; - GlyphStore(uv_loop_t* loop); + GlyphStore(); ~GlyphStore(); - // Asynchronously request for GlyphRanges and when it gets loaded, notifies the - // observer subscribed to this object. Successive requests for the same range are - // going to be discarded. Returns true if a request was made or false if all the - // GlyphRanges are already available, and thus, no request is performed. - bool requestGlyphRangesIfNeeded(const std::string &fontStack, const std::set &glyphRanges); + util::exclusive getFontStack(const std::string& fontStack); - util::exclusive getFontStack(const std::string &fontStack); + bool hasGlyphRanges(const std::string& fontStackName, const std::set& glyphRanges); - void setURL(const std::string &url); + void setURL(const std::string &url) { + glyphURL = url; + } void setObserver(Observer* observer); private: void emitGlyphRangeLoaded(); - void emitGlyphRangeLoadingFailed(); + void emitGlyphRangeLoadingFailed(const std::string& message); util::exclusive createFontStack(const std::string &fontStack); + void requestGlyphRange(const std::string& fontStackName, const GlyphRange& range); std::string glyphURL; @@ -61,13 +55,9 @@ private: std::unordered_map> stacks; std::mutex stacksMutex; - std::string errorMessage; - std::mutex errorMessageMutex; + util::WorkQueue workQueue; - std::unique_ptr asyncEmitGlyphRangeLoaded; - std::unique_ptr asyncEmitGlyphRangeLoadedingFailed; - - Observer* observer; + Observer* observer = nullptr; }; } From cd2c1200c87afbe05bd2d63caa0959a0fff32d94 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 30 Jun 2015 10:49:34 +0300 Subject: [PATCH 39/41] Add GlyphStore unit tests --- test/style/glyph_store.cpp | 225 +++++++++++++++++++++++++++++++++++++ test/test.gypi | 1 + 2 files changed, 226 insertions(+) create mode 100644 test/style/glyph_store.cpp diff --git a/test/style/glyph_store.cpp b/test/style/glyph_store.cpp new file mode 100644 index 000000000..fb4355b98 --- /dev/null +++ b/test/style/glyph_store.cpp @@ -0,0 +1,225 @@ +#include "../fixtures/fixture_log_observer.hpp" +#include "../fixtures/mock_file_source.hpp" +#include "../fixtures/util.hpp" + +#include +#include +#include +#include + +using namespace mbgl; + +using GlyphStoreTestCallback = std::function; + +struct GlyphStoreParams { + const std::string url; + const std::string stack; + const std::set ranges; +}; + +class GlyphStoreThread : public GlyphStore::Observer { +public: + GlyphStoreThread(FileSource* fileSource, GlyphStoreTestCallback callback) : callback_(callback) { + util::ThreadContext::setFileSource(fileSource); + } + + void loadGlyphStore(const GlyphStoreParams& params) { + glyphStore_.reset(new GlyphStore()); + + glyphStore_->setObserver(this); + glyphStore_->setURL(params.url); + + ASSERT_FALSE(glyphStore_->hasGlyphRanges(params.stack, params.ranges)); + } + + void unloadGlyphStore() { + glyphStore_->setObserver(nullptr); + glyphStore_.reset(); + } + + void onGlyphRangeLoaded() override { + callback_(glyphStore_.get(), nullptr); + } + + void onGlyphRangeLoadingFailed(std::exception_ptr error) override { + callback_(glyphStore_.get(), error); + } + +private: + std::unique_ptr glyphStore_; + GlyphStoreTestCallback callback_; +}; + +class GlyphStoreTest : public testing::Test { +protected: + void runTest(const GlyphStoreParams& params, FileSource* fileSource, GlyphStoreTestCallback callback) { + util::RunLoop loop(uv_default_loop()); + + async_ = std::make_unique(loop.get(), [&]{ loop.stop(); }); + async_->unref(); + + const util::ThreadContext context = {"Map", util::ThreadType::Map, util::ThreadPriority::Regular}; + + util::Thread tester(context, fileSource, callback); + tester.invoke(&GlyphStoreThread::loadGlyphStore, params); + + uv_run(loop.get(), UV_RUN_DEFAULT); + + tester.invoke(&GlyphStoreThread::unloadGlyphStore); + } + + void stopTest() { + testDone = true; + async_->send(); + } + + bool isDone() const { + return testDone; + } + +private: + bool testDone = false; + + std::unique_ptr async_; +}; + +TEST_F(GlyphStoreTest, LoadingSuccess) { + GlyphStoreParams params = { + "test/fixtures/resources/glyphs.pbf", + "Test Stack", + {{0, 255}, {256, 511}} + }; + + auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) { + ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map)); + + // We need to check if the test is over because checking + // if the GlyphStore has glyphs below will cause more requests + // to happen and we don't want this endless loop. + if (isDone()) { + return; + } + + ASSERT_EQ(error, nullptr); + + if (!store->hasGlyphRanges(params.stack, params.ranges)) { + return; + } + + ASSERT_FALSE(store->hasGlyphRanges("Foobar", params.ranges)); + ASSERT_FALSE(store->hasGlyphRanges("Foobar", {{512, 767}})); + ASSERT_FALSE(store->hasGlyphRanges("Test Stack", {{512, 767}})); + + auto fontStack = store->getFontStack(params.stack); + ASSERT_FALSE(fontStack->getMetrics().empty()); + ASSERT_FALSE(fontStack->getSDFs().empty()); + + stopTest(); + }; + + MockFileSource fileSource(MockFileSource::Success, ""); + runTest(params, &fileSource, callback); +} + +TEST_F(GlyphStoreTest, LoadingFail) { + GlyphStoreParams params = { + "test/fixtures/resources/glyphs.pbf", + "Test Stack", + {{0, 255}, {256, 511}} + }; + + auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) { + ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map)); + + if (isDone()) { + return; + } + + ASSERT_TRUE(error != nullptr); + + auto fontStack = store->getFontStack(params.stack); + ASSERT_EQ(*fontStack, nullptr); + + for (const auto& range : params.ranges) { + ASSERT_FALSE(store->hasGlyphRanges(params.stack, {range})); + } + + ASSERT_FALSE(store->hasGlyphRanges(params.stack, params.ranges)); + ASSERT_FALSE(store->hasGlyphRanges("Foobar", params.ranges)); + ASSERT_FALSE(store->hasGlyphRanges("Foobar", {{512, 767}})); + + stopTest(); + }; + + MockFileSource fileSource(MockFileSource::RequestFail, "glyphs.pbf"); + runTest(params, &fileSource, callback); +} + +TEST_F(GlyphStoreTest, LoadingCorrupted) { + GlyphStoreParams params = { + "test/fixtures/resources/glyphs.pbf", + "Test Stack", + {{0, 255}, {256, 511}} + }; + + auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) { + ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map)); + + if (isDone()) { + return; + } + + ASSERT_TRUE(error != nullptr); + + for (const auto& range : params.ranges) { + ASSERT_FALSE(store->hasGlyphRanges(params.stack, {range})); + } + + ASSERT_FALSE(store->hasGlyphRanges(params.stack, params.ranges)); + ASSERT_FALSE(store->hasGlyphRanges("Foobar", params.ranges)); + ASSERT_FALSE(store->hasGlyphRanges("Foobar", {{512, 767}})); + + stopTest(); + }; + + MockFileSource fileSource(MockFileSource::RequestWithCorruptedData, "glyphs.pbf"); + runTest(params, &fileSource, callback); +} + +TEST_F(GlyphStoreTest, LoadingCancel) { + GlyphStoreParams params = { + "test/fixtures/resources/glyphs.pbf", + "Test Stack", + {{0, 255}, {256, 511}} + }; + + auto callback = [this](GlyphStore*, std::exception_ptr) { + FAIL() << "Should never be called"; + }; + + MockFileSource fileSource(MockFileSource::SuccessWithDelay, "glyphs.pbf"); + fileSource.setOnRequestDelayedCallback([this]{ + stopTest(); + }); + runTest(params, &fileSource, callback); +} + +TEST_F(GlyphStoreTest, InvalidURL) { + GlyphStoreParams params = { + "foo bar", + "Test Stack", + {{0, 255}, {256, 511}} + }; + + auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) { + ASSERT_TRUE(error != nullptr); + + auto fontStack = store->getFontStack(params.stack); + ASSERT_EQ(*fontStack, nullptr); + + stopTest(); + }; + + MockFileSource fileSource(MockFileSource::Success, ""); + runTest(params, &fileSource, callback); +} diff --git a/test/test.gypi b/test/test.gypi index 7d97290c8..142445d98 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -88,6 +88,7 @@ 'storage/http_other_loop.cpp', 'storage/http_reading.cpp', + 'style/glyph_store.cpp', 'style/pending_resources.cpp', 'style/resource_loading.cpp', 'style/sprite.cpp', From dd818874cc1d959960e428dfcf93c7ed4bf78160 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Wed, 15 Jul 2015 12:02:58 +0300 Subject: [PATCH 40/41] Remove hacks because of Glyph requests could not be canceled --- src/mbgl/util/worker.cpp | 8 ++------ test/style/pending_resources.cpp | 5 ----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp index 60adbc803..516d2f5db 100644 --- a/src/mbgl/util/worker.cpp +++ b/src/mbgl/util/worker.cpp @@ -14,11 +14,7 @@ namespace mbgl { class Worker::Impl { public: - explicit Impl(FileSource* fs) { - // FIXME: Workers should not access the FileSource but it - // is currently needed because of GlyphsPBF. See #1664. - util::ThreadContext::setFileSource(fs); - } + Impl() = default; void parseRasterTile(RasterBucket* bucket, std::string data, std::function callback) { std::unique_ptr image(new util::Image(data)); @@ -59,7 +55,7 @@ public: Worker::Worker(std::size_t count) { util::ThreadContext context = {"Worker", util::ThreadType::Worker, util::ThreadPriority::Low}; for (std::size_t i = 0; i < count; i++) { - threads.emplace_back(std::make_unique>(context, util::ThreadContext::getFileSource())); + threads.emplace_back(std::make_unique>(context)); } } diff --git a/test/style/pending_resources.cpp b/test/style/pending_resources.cpp index 4513d1864..3ba59657d 100644 --- a/test/style/pending_resources.cpp +++ b/test/style/pending_resources.cpp @@ -21,11 +21,6 @@ class PendingResources : public ::testing::TestWithParam { // the Map object after that. The idea here is to test if these pending requests // are getting canceled correctly if on shutdown. TEST_P(PendingResources, DeleteMapObjectWithPendingRequest) { - // TODO: The glyphs test is blocked by the issue #1664. - if (GetParam() == "glyphs.pbf") { - return; - } - util::RunLoop loop(uv_default_loop()); auto display = std::make_shared(); From 38351554f45e02c1c7b59beeb11f5675d22f19b3 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Thu, 16 Jul 2015 17:32:44 +0300 Subject: [PATCH 41/41] Only print Sprite warnings if we have Sprites set If we don't set Sprites at all or the Sprites were not loaded yet, the warnings can be misleading. --- src/mbgl/annotation/sprite_store.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mbgl/annotation/sprite_store.cpp b/src/mbgl/annotation/sprite_store.cpp index 1c6511d8e..8d2231a2b 100644 --- a/src/mbgl/annotation/sprite_store.cpp +++ b/src/mbgl/annotation/sprite_store.cpp @@ -54,7 +54,9 @@ std::shared_ptr SpriteStore::getSprite(const std::string& nam if (it != sprites.end()) { return it->second; } else { - Log::Info(Event::Sprite, "Can't find sprite named '%s'", name.c_str()); + if (!sprites.empty()) { + Log::Info(Event::Sprite, "Can't find sprite named '%s'", name.c_str()); + } return nullptr; } }