summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------.mason0
-rw-r--r--.travis.yml2
-rw-r--r--README.md11
-rw-r--r--include/mbgl/platform/event.hpp4
-rw-r--r--ios/benchmark/MBXBenchViewController.mm2
-rwxr-xr-xios/docs/install_docs.sh2
-rw-r--r--platform/ios/MGLMapboxEvents.m32
-rw-r--r--platform/ios/resources/star_tilestream_net.derbin0 -> 1338 bytes
-rwxr-xr-xscripts/ios/install.sh6
-rwxr-xr-xscripts/ios/package.sh2
-rw-r--r--src/mbgl/map/map_context.cpp38
-rw-r--r--src/mbgl/map/map_context.hpp16
-rw-r--r--src/mbgl/map/resource_loader.cpp160
-rw-r--r--src/mbgl/map/resource_loader.hpp91
-rw-r--r--src/mbgl/renderer/painter.cpp22
-rw-r--r--src/mbgl/renderer/painter.hpp8
-rw-r--r--src/mbgl/renderer/painter_fill.cpp6
-rw-r--r--src/mbgl/renderer/painter_line.cpp14
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp10
-rw-r--r--src/mbgl/style/style.cpp181
-rw-r--r--src/mbgl/style/style.hpp66
-rw-r--r--test/ios/MetricsTests.m21
-rw-r--r--test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme9
-rw-r--r--test/miscellaneous/style_parser.cpp28
-rw-r--r--test/style/mock_file_source.cpp (renamed from test/resources/mock_file_source.cpp)0
-rw-r--r--test/style/mock_file_source.hpp (renamed from test/resources/mock_file_source.hpp)0
-rw-r--r--test/style/mock_view.hpp (renamed from test/resources/mock_view.hpp)0
-rw-r--r--test/style/resource_loading.cpp (renamed from test/resources/resource_loader.cpp)70
-rw-r--r--test/test.gypi10
29 files changed, 347 insertions, 464 deletions
diff --git a/.mason b/.mason
-Subproject ace19da711199cb0283c6243b435575fbec16a9
+Subproject abdc131273c3e50e42f245b1166c27de4c34c58
diff --git a/.travis.yml b/.travis.yml
index 1ac66b3862..e5b94a813a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,8 +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
env: FLAVOR=osx BUILDTYPE=Debug
- os: osx
+ osx_image: beta-xcode6.3
env: FLAVOR=ios BUILDTYPE=Release
- os: linux
env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Release
diff --git a/README.md b/README.md
index 389f03242b..625e970faa 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,15 @@ pod 'MapboxGL'
#### Manually
-1. Install [appledoc](http://appledoc.gentlebytes.com/appledoc/) for API docs generation. We recommend [`2.2v963`](https://github.com/tomaz/appledoc/releases/tag/v2.2-963), which currently isn't available in Homebrew.
+1. Install [appledoc](http://appledoc.gentlebytes.com/appledoc/) 2.2v963 for API docs generation (only this exact version works).
+
+ ```
+ curl -L -o appledoc.zip https://github.com/tomaz/appledoc/releases/download/v2.2-963/appledoc.zip
+ unzip appledoc.zip
+ cp appledoc /usr/local/bin
+ cp -Rf Templates/ ~/.appledoc
+ ```
+
1. Run `make ipackage`. The packaging script will produce the statically-linked `libMapboxGL.a`, `MapboxGL.bundle` for resources, a `Headers` folder, and a `Docs` folder with HTML API documentation.
1. Copy the contents of `build/ios/pkg/static` into your project. It should happen automatically, but ensure that:
- `Headers` is in your *Header Search Paths* (`HEADER_SEARCH_PATHS`) build setting.
@@ -82,6 +90,7 @@ pod 'MapboxGL'
If you want to build from source and/or contribute to development of the project, run `make iproj`, which will create and open an Xcode project which can build the entire library from source as well as an Objective-C test app. If you don't have an Apple Developer account, change the destination from "My Mac" to a simulator such as "iPhone 6" before you run and build the app.
+#### Testing
You can run `make itest` to run the included integration tests. Requires `gem install xcpretty`. If you want to run the tests in Xcode instead, first `make ipackage` to create a local static library version, then open `test/ios/ios-tests.xcodeproj`, and lastly `Command + U` on the `Mapbox GL Tests` application target.
Target devices: iPhone 4S and above (5, 5c, 5s, 6, 6 Plus) and iPad 2 and above (3, 4, Mini, Air, Mini 2, Air 2).
diff --git a/include/mbgl/platform/event.hpp b/include/mbgl/platform/event.hpp
index 8cdd1d50a9..c80186da27 100644
--- a/include/mbgl/platform/event.hpp
+++ b/include/mbgl/platform/event.hpp
@@ -29,7 +29,7 @@ enum class Event : uint8_t {
ParseStyle,
ParseTile,
Render,
- ResourceLoader,
+ Style,
Database,
HttpRequest,
Sprite,
@@ -47,7 +47,7 @@ MBGL_DEFINE_ENUM_CLASS(EventClass, Event, {
{ Event::ParseStyle, "ParseStyle" },
{ Event::ParseTile, "ParseTile" },
{ Event::Render, "Render" },
- { Event::ResourceLoader, "ResourceLoader" },
+ { Event::Style, "Style" },
{ Event::Database, "Database" },
{ Event::HttpRequest, "HttpRequest" },
{ Event::Sprite, "Sprite" },
diff --git a/ios/benchmark/MBXBenchViewController.mm b/ios/benchmark/MBXBenchViewController.mm
index dfd3b254a3..8883ebff0f 100644
--- a/ios/benchmark/MBXBenchViewController.mm
+++ b/ios/benchmark/MBXBenchViewController.mm
@@ -33,7 +33,7 @@
[super viewDidLoad];
NSURL* url = [[NSURL alloc] initWithString:@"asset://styles/mapbox-streets-v7.json"];
- self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds accessToken:nil styleURL:url];
+ self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:url];
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.mapView.delegate = self;
self.mapView.zoomEnabled = NO;
diff --git a/ios/docs/install_docs.sh b/ios/docs/install_docs.sh
index 7d4bf279f3..8fa768b997 100755
--- a/ios/docs/install_docs.sh
+++ b/ios/docs/install_docs.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
if [ -z `which appledoc` ]; then
- echo "Unable to find appledoc. Consider installing it from source or Homebrew."
+ echo "Unable to find appledoc. See https://github.com/mapbox/mapbox-gl-native#manually"
exit 1
fi
diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m
index e7f400c5dc..bf730af945 100644
--- a/platform/ios/MGLMapboxEvents.m
+++ b/platform/ios/MGLMapboxEvents.m
@@ -148,6 +148,8 @@ const NSTimeInterval MGLFlushInterval = 60;
@property (atomic) NSURLSession *session;
@property (atomic) NSData *digicertCert;
@property (atomic) NSData *geoTrustCert;
+@property (atomic) NSData *testServerCert;
+@property (atomic) BOOL usesTestServer;
// Main thread only
@property (nonatomic) CLLocationManager *locationManager;
@@ -239,6 +241,10 @@ const NSTimeInterval MGLFlushInterval = 60;
NSString *testURL = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLMetricsTestServerURL"];
if (testURL != nil) {
MGLMapboxEventsAPIBase = testURL;
+ _usesTestServer = YES;
+ } else {
+ // Explicitly Set For Clarity
+ _usesTestServer = NO;
}
_paused = YES;
@@ -256,6 +262,10 @@ const NSTimeInterval MGLFlushInterval = 60;
if (cerPath != nil) {
_digicertCert = [NSData dataWithContentsOfFile:cerPath];
}
+ cerPath = [resourceBundle pathForResource:@"star_tilestream_net" ofType:@"der"];
+ if (cerPath != nil) {
+ _testServerCert = [NSData dataWithContentsOfFile:cerPath];
+ }
// Events Control
_eventQueue = [[NSMutableArray alloc] init];
@@ -848,7 +858,7 @@ const NSTimeInterval MGLFlushInterval = 60;
// Look for a pinned certificate in the server's certificate chain
long numKeys = SecTrustGetCertificateCount(serverTrust);
- BOOL found = false;
+ BOOL found = NO;
// Try GeoTrust Cert First
for (int lc = 0; lc < numKeys; lc++) {
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, lc);
@@ -858,7 +868,7 @@ const NSTimeInterval MGLFlushInterval = 60;
if ([remoteCertificateData isEqualToData:_geoTrustCert]) {
// Found the certificate; continue connecting
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
- found = true;
+ found = YES;
break;
}
}
@@ -873,11 +883,27 @@ const NSTimeInterval MGLFlushInterval = 60;
if ([remoteCertificateData isEqualToData:_digicertCert]) {
// Found the certificate; continue connecting
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
- found = true;
+ found = YES;
break;
}
}
+ if (!found && _usesTestServer) {
+ // See if this is test server
+ for (int lc = 0; lc < numKeys; lc++) {
+ SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, lc);
+ NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
+
+ // Compare Remote Key With Local Version
+ if ([remoteCertificateData isEqualToData:_testServerCert]) {
+ // Found the certificate; continue connecting
+ completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
+ found = YES;
+ break;
+ }
+ }
+ }
+
if (!found) {
// The certificate wasn't found in GeoTrust nor Digicert. Cancel the connection.
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
diff --git a/platform/ios/resources/star_tilestream_net.der b/platform/ios/resources/star_tilestream_net.der
new file mode 100644
index 0000000000..e302cd7686
--- /dev/null
+++ b/platform/ios/resources/star_tilestream_net.der
Binary files differ
diff --git a/scripts/ios/install.sh b/scripts/ios/install.sh
index ffa714f36f..da081254f8 100755
--- a/scripts/ios/install.sh
+++ b/scripts/ios/install.sh
@@ -15,4 +15,10 @@ brew install git
mapbox_time "install_awscli" \
brew install awscli
+mapbox_time "install_appledoc" \
+wget https://github.com/tomaz/appledoc/releases/download/v2.2-963/appledoc.zip && \
+tar xvzf appledoc.zip && \
+cp appledoc /usr/local/bin && \
+cp -Rf Templates/ ~/.appledoc
+
mkdir -p ${KIF_SCREENSHOTS}
diff --git a/scripts/ios/package.sh b/scripts/ios/package.sh
index 35162ce5d1..e4bba0e9f6 100755
--- a/scripts/ios/package.sh
+++ b/scripts/ios/package.sh
@@ -98,7 +98,7 @@ cp -prv styles/styles "${OUTPUT}/static/${NAME}.bundle/styles"
step "Creating API Docs..."
if [ -z `which appledoc` ]; then
- echo "Unable to find appledoc. Consider installing it from source or Homebrew."
+ echo "Unable to find appledoc. See https://github.com/mapbox/mapbox-gl-native#manually"
exit 1
fi
DOCS_OUTPUT="${OUTPUT}/static/Docs"
diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp
index c8948097f7..a834f50655 100644
--- a/src/mbgl/map/map_context.cpp
+++ b/src/mbgl/map/map_context.cpp
@@ -2,19 +2,12 @@
#include <mbgl/map/map_data.hpp>
#include <mbgl/map/view.hpp>
#include <mbgl/map/environment.hpp>
-#include <mbgl/map/source.hpp>
#include <mbgl/map/still_image.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/text/glyph_store.hpp>
-
-#include <mbgl/geometry/glyph_atlas.hpp>
-#include <mbgl/geometry/sprite_atlas.hpp>
-#include <mbgl/geometry/line_atlas.hpp>
-
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
@@ -34,10 +27,6 @@ MapContext::MapContext(uv_loop_t* loop, View& view_, FileSource& fileSource, Map
envScope(env, ThreadType::Map, "Map"),
updated(static_cast<UpdateType>(Update::Nothing)),
asyncUpdate(std::make_unique<uv::async>(loop, [this] { update(); })),
- glyphStore(std::make_unique<GlyphStore>(loop, env)),
- glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)),
- spriteAtlas(std::make_unique<SpriteAtlas>(512, 512)),
- lineAtlas(std::make_unique<LineAtlas>(512, 512)),
texturePool(std::make_unique<TexturePool>()) {
assert(Environment::currentlyOn(ThreadType::Map));
@@ -51,14 +40,9 @@ MapContext::~MapContext() {
// Explicit resets currently necessary because these abandon resources that need to be
// cleaned up by env.performCleanup();
- resourceLoader.reset();
style.reset();
painter.reset();
texturePool.reset();
- lineAtlas.reset();
- spriteAtlas.reset();
- glyphAtlas.reset();
- glyphStore.reset();
env.performCleanup();
@@ -116,21 +100,11 @@ void MapContext::setStyleJSON(const std::string& json, const std::string& base)
void MapContext::loadStyleJSON(const std::string& json, const std::string& base) {
assert(Environment::currentlyOn(ThreadType::Map));
- resourceLoader.reset();
style.reset();
-
- style = std::make_unique<Style>();
- style->base = base;
- style->loadJSON((const uint8_t *)json.c_str());
+ style = std::make_unique<Style>(json, base, asyncUpdate->get()->loop, env);
style->cascade(data.getClasses());
style->setDefaultTransitionDuration(data.getDefaultTransitionDuration());
-
- glyphStore->setURL(style->glyph_url);
-
- resourceLoader = std::make_unique<ResourceLoader>();
- resourceLoader->setObserver(this);
- resourceLoader->setStyle(style.get());
- resourceLoader->setGlyphStore(glyphStore.get());
+ style->setObserver(this);
triggerUpdate(Update::Zoom);
}
@@ -138,7 +112,7 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base)
void MapContext::updateTiles() {
assert(Environment::currentlyOn(ThreadType::Map));
- resourceLoader->update(data, transformState, *glyphAtlas, *spriteAtlas, *texturePool);
+ style->update(data, transformState, *texturePool);
}
void MapContext::updateAnnotationTiles(const std::vector<TileID>& ids) {
@@ -177,7 +151,7 @@ void MapContext::update() {
updateTiles();
- if (style->isLoaded() && resourceLoader->getSprite()->isLoaded()) {
+ if (style->isLoaded()) {
if (!data.getFullyLoaded()) {
data.setFullyLoaded(true);
}
@@ -220,7 +194,7 @@ void MapContext::render() {
assert(style);
if (!painter) {
- painter = std::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas);
+ painter = std::make_unique<Painter>();
painter->setup();
}
@@ -240,7 +214,7 @@ void MapContext::render() {
double MapContext::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) {
assert(Environment::currentlyOn(ThreadType::Map));
- const SpritePosition pos = resourceLoader->getSprite()->getSpritePosition(symbol);
+ const SpritePosition pos = style->sprite->getSpritePosition(symbol);
return -pos.height / pos.pixelRatio / 2;
}
diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp
index fb9fdb4d4b..8894434242 100644
--- a/src/mbgl/map/map_context.hpp
+++ b/src/mbgl/map/map_context.hpp
@@ -4,8 +4,8 @@
#include <mbgl/map/tile_id.hpp>
#include <mbgl/map/update.hpp>
#include <mbgl/map/environment.hpp>
-#include <mbgl/map/resource_loader.hpp>
#include <mbgl/map/transform_state.hpp>
+#include <mbgl/style/style.hpp>
#include <mbgl/util/ptr.hpp>
#include <vector>
@@ -20,20 +20,15 @@ namespace mbgl {
class View;
class MapData;
-class GlyphStore;
-class GlyphAtlas;
-class SpriteAtlas;
-class LineAtlas;
class TexturePool;
class Painter;
class Sprite;
-class Style;
class Worker;
class StillImage;
struct LatLng;
struct LatLngBounds;
-class MapContext : public ResourceLoader::Observer {
+class MapContext : public Style::Observer {
public:
MapContext(uv_loop_t*, View&, FileSource&, MapData&);
~MapContext();
@@ -59,7 +54,7 @@ public:
void setSourceTileCacheSize(size_t size);
void onLowMemory();
- // ResourceLoader::Observer implementation.
+ // Style::Observer implementation.
void onTileDataChanged() override;
void onResourceLoadingFailed(std::exception_ptr error) override;
@@ -81,14 +76,9 @@ private:
UpdateType updated { static_cast<UpdateType>(Update::Nothing) };
std::unique_ptr<uv::async> asyncUpdate;
- std::unique_ptr<GlyphStore> glyphStore;
- std::unique_ptr<GlyphAtlas> glyphAtlas;
- std::unique_ptr<SpriteAtlas> spriteAtlas;
- std::unique_ptr<LineAtlas> lineAtlas;
std::unique_ptr<TexturePool> texturePool;
std::unique_ptr<Painter> painter;
std::unique_ptr<Style> style;
- std::unique_ptr<ResourceLoader> resourceLoader;
std::string styleURL;
std::string styleJSON;
diff --git a/src/mbgl/map/resource_loader.cpp b/src/mbgl/map/resource_loader.cpp
deleted file mode 100644
index 8e054c0d82..0000000000
--- a/src/mbgl/map/resource_loader.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-#include <mbgl/map/resource_loader.hpp>
-
-#include <mbgl/geometry/sprite_atlas.hpp>
-#include <mbgl/map/environment.hpp>
-#include <mbgl/map/source.hpp>
-#include <mbgl/map/sprite.hpp>
-#include <mbgl/map/transform.hpp>
-#include <mbgl/style/style.hpp>
-
-#include <cassert>
-
-namespace mbgl {
-
-ResourceLoader::ResourceLoader() {
- assert(Environment::currentlyOn(ThreadType::Map));
-}
-
-ResourceLoader::~ResourceLoader() {
- assert(Environment::currentlyOn(ThreadType::Map));
-
- for (const auto& source : style_->sources) {
- source->setObserver(nullptr);
- }
-
- if (sprite_) {
- sprite_->setObserver(nullptr);
- }
-
- if (glyphStore_) {
- glyphStore_->setObserver(nullptr);
- }
-}
-
-void ResourceLoader::setObserver(Observer* observer) {
- assert(Environment::currentlyOn(ThreadType::Map));
- assert(!observer_);
-
- observer_ = observer;
-}
-
-void ResourceLoader::setStyle(Style* style) {
- assert(style);
-
- style_ = style;
-
- for (const auto& source : style->sources) {
- source->setObserver(this);
- source->load();
- }
-}
-
-void ResourceLoader::setGlyphStore(GlyphStore* glyphStore) {
- assert(glyphStore);
-
- if (glyphStore_) {
- glyphStore_->setObserver(nullptr);
- }
-
- glyphStore_ = glyphStore;
- glyphStore_->setObserver(this);
-}
-
-void ResourceLoader::update(MapData& data,
- const TransformState& transform,
- GlyphAtlas& glyphAtlas,
- SpriteAtlas& spriteAtlas,
- TexturePool& texturePool) {
- if (!style_) {
- return;
- }
-
- const float pixelRatio = transform.getPixelRatio();
- if (!sprite_ || !sprite_->hasPixelRatio(pixelRatio)) {
- sprite_ = std::make_unique<Sprite>(style_->getSpriteURL(), pixelRatio);
- sprite_->setObserver(this);
-
- spriteAtlas.resize(pixelRatio);
- spriteAtlas.setSprite(sprite_);
- }
-
- bool allTilesUpdated = true;
- for (const auto& source : style_->sources) {
- if (!source->update(data, transform, *style_, glyphAtlas, *glyphStore_,
- spriteAtlas, sprite_, texturePool, shouldReparsePartialTiles_)) {
- allTilesUpdated = false;
- }
- }
-
- // We can only stop updating "partial" tiles when all of them
- // were notified of the arrival of the new resources.
- if (allTilesUpdated) {
- shouldReparsePartialTiles_ = false;
- }
-}
-
-void ResourceLoader::onGlyphRangeLoaded() {
- shouldReparsePartialTiles_ = true;
-
- emitTileDataChanged();
-}
-
-void ResourceLoader::onGlyphRangeLoadingFailed(std::exception_ptr error) {
- emitResourceLoadingFailed(error);
-}
-
-void ResourceLoader::onSourceLoaded() {
- emitTileDataChanged();
-}
-
-void ResourceLoader::onSourceLoadingFailed(std::exception_ptr error) {
- emitResourceLoadingFailed(error);
-}
-
-void ResourceLoader::onTileLoaded(bool isNewTile) {
- if (isNewTile) {
- shouldReparsePartialTiles_ = true;
- }
-
- emitTileDataChanged();
-}
-
-void ResourceLoader::onTileLoadingFailed(std::exception_ptr error) {
- emitResourceLoadingFailed(error);
-}
-
-void ResourceLoader::onSpriteLoaded() {
- shouldReparsePartialTiles_ = true;
-
- emitTileDataChanged();
-}
-
-void ResourceLoader::onSpriteLoadingFailed(std::exception_ptr error) {
- emitResourceLoadingFailed(error);
-}
-
-void ResourceLoader::emitTileDataChanged() {
- assert(Environment::currentlyOn(ThreadType::Map));
-
- if (observer_) {
- observer_->onTileDataChanged();
- }
-}
-
-void ResourceLoader::emitResourceLoadingFailed(std::exception_ptr error) {
- assert(Environment::currentlyOn(ThreadType::Map));
-
- try {
- if (error) {
- std::rethrow_exception(error);
- }
- } catch(const std::exception& e) {
- Log::Error(Event::ResourceLoader, e.what());
- }
-
- if (observer_) {
- observer_->onResourceLoadingFailed(error);
- }
-}
-
-}
diff --git a/src/mbgl/map/resource_loader.hpp b/src/mbgl/map/resource_loader.hpp
deleted file mode 100644
index 525e4653a0..0000000000
--- a/src/mbgl/map/resource_loader.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef MBGL_MAP_RESOURCE_LOADER
-#define MBGL_MAP_RESOURCE_LOADER
-
-#include <mbgl/map/source.hpp>
-#include <mbgl/map/sprite.hpp>
-#include <mbgl/text/glyph_store.hpp>
-#include <mbgl/util/noncopyable.hpp>
-
-#include <string>
-
-namespace mbgl {
-
-class GlyphAtlas;
-class GlyphStore;
-class MapData;
-class SpriteAtlas;
-class Style;
-class TexturePool;
-class TransformState;
-
-// ResourceLoader is responsible for loading and updating the Source(s) owned
-// by the Style. The Source object currently owns all the tiles, thus this
-// class will notify its observers of any change on these tiles which will
-// ultimately cause a new rendering to be triggered.
-class ResourceLoader : public GlyphStore::Observer,
- public Source::Observer,
- public Sprite::Observer,
- private util::noncopyable {
-public:
- class Observer {
- public:
- virtual ~Observer() = default;
-
- virtual void onTileDataChanged() = 0;
- virtual void onResourceLoadingFailed(std::exception_ptr error) = 0;
- };
-
- ResourceLoader();
- ~ResourceLoader();
-
- void setObserver(Observer* observer);
-
- // The style object currently owns all the sources. When setting
- // a new style we will go through all of them and try to load.
- void setStyle(Style* style);
-
- // TODO: Move GlyphStore to ResourceLoader. We cannot do it now
- // because we reset the ResourceLoader every time we change the
- // style.
- void setGlyphStore(GlyphStore* glyphStore);
-
- // Fetch the tiles needed by the current viewport and emit a signal when
- // a tile is ready so observers can render the tile.
- void update(MapData&, const TransformState&, GlyphAtlas&, SpriteAtlas&, TexturePool&);
-
- // FIXME: There is probably a better place for this.
- inline util::ptr<Sprite> getSprite() const {
- return sprite_;
- }
-
- // GlyphStore::Observer implementation.
- void onGlyphRangeLoaded() override;
- void onGlyphRangeLoadingFailed(std::exception_ptr error) override;
-
- // Source::Observer implementation.
- void onSourceLoaded() override;
- void onSourceLoadingFailed(std::exception_ptr error) override;
- void onTileLoaded(bool isNewTile) override;
- void onTileLoadingFailed(std::exception_ptr error) override;
-
- // Sprite::Observer implementation.
- void onSpriteLoaded() override;
- void onSpriteLoadingFailed(std::exception_ptr error) override;
-
-private:
- void emitTileDataChanged();
- void emitResourceLoadingFailed(std::exception_ptr error);
-
- bool shouldReparsePartialTiles_ = false;
-
- util::ptr<Sprite> sprite_;
-
- GlyphStore* glyphStore_ = nullptr;
- Style* style_ = nullptr;
-
- Observer* observer_ = nullptr;
-};
-
-}
-
-#endif
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 977b6e565f..43d06b69d1 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -42,11 +42,7 @@ using namespace mbgl;
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
-Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_, LineAtlas& lineAtlas_)
- : spriteAtlas(spriteAtlas_)
- , glyphAtlas(glyphAtlas_)
- , lineAtlas(lineAtlas_)
-{
+Painter::Painter() {
}
Painter::~Painter() {
@@ -173,6 +169,10 @@ void Painter::prepareTile(const Tile& tile) {
void Painter::render(const Style& style, TransformState state_, TimePoint time) {
state = state_;
+ glyphAtlas = style.glyphAtlas.get();
+ spriteAtlas = style.spriteAtlas.get();
+ lineAtlas = style.lineAtlas.get();
+
std::set<Source*> sources;
for (const auto& source : style.sources) {
if (source->enabled) {
@@ -193,9 +193,9 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
tileStencilBuffer.upload();
tileBorderBuffer.upload();
- spriteAtlas.upload();
- lineAtlas.upload();
- glyphAtlas.upload();
+ spriteAtlas->upload();
+ lineAtlas->upload();
+ glyphAtlas->upload();
for (const auto& item : order) {
if (item.bucket && item.bucket->needsUpload()) {
@@ -391,8 +391,8 @@ void Painter::renderBackground(const StyleLayer &layer_desc) {
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
return;
- SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true);
- SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true);
+ SpriteAtlasPosition imagePosA = spriteAtlas->getPosition(properties.image.from, true);
+ SpriteAtlasPosition imagePosB = spriteAtlas->getPosition(properties.image.to, true);
float zoomFraction = state.getZoomFraction();
useProgram(patternShader->program);
@@ -441,7 +441,7 @@ void Painter::renderBackground(const StyleLayer &layer_desc) {
backgroundBuffer.bind();
patternShader->bind(0);
- spriteAtlas.bind(true);
+ spriteAtlas->bind(true);
} else {
Color color = properties.color;
color[0] *= properties.opacity;
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 29f17108d3..465bf5ba33 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -79,7 +79,7 @@ struct RenderItem {
class Painter : private util::noncopyable {
public:
- Painter(SpriteAtlas&, GlyphAtlas&, LineAtlas&);
+ Painter();
~Painter();
void setup();
@@ -204,9 +204,9 @@ private:
public:
FrameHistory frameHistory;
- SpriteAtlas& spriteAtlas;
- GlyphAtlas& glyphAtlas;
- LineAtlas& lineAtlas;
+ SpriteAtlas* spriteAtlas;
+ GlyphAtlas* glyphAtlas;
+ LineAtlas* lineAtlas;
std::unique_ptr<PlainShader> plainShader;
std::unique_ptr<OutlineShader> outlineShader;
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index b2fdafadbd..5514ebc858 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -63,8 +63,8 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const
// Image fill.
if (pass == RenderPass::Translucent) {
- const SpriteAtlasPosition posA = spriteAtlas.getPosition(properties.image.from, true);
- const SpriteAtlasPosition posB = spriteAtlas.getPosition(properties.image.to, true);
+ const SpriteAtlasPosition posA = spriteAtlas->getPosition(properties.image.from, true);
+ const SpriteAtlasPosition posB = spriteAtlas->getPosition(properties.image.to, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z) / id.overscaling;
mat3 patternMatrixA;
@@ -91,7 +91,7 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const
patternShader->u_patternmatrix_b = patternMatrixB;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
- spriteAtlas.bind(true);
+ spriteAtlas->bind(true);
// Draw the actual triangles into the color & stencil buffer.
config.depthMask = GL_TRUE;
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 612e04e121..e084147deb 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -66,9 +66,9 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
linesdfShader->u_blur = blur;
linesdfShader->u_color = color;
- LinePatternPos posA = lineAtlas.getDashPosition(properties.dash_array.from, layout.cap == CapType::Round);
- LinePatternPos posB = lineAtlas.getDashPosition(properties.dash_array.to, layout.cap == CapType::Round);
- lineAtlas.bind();
+ LinePatternPos posA = lineAtlas->getDashPosition(properties.dash_array.from, layout.cap == CapType::Round);
+ LinePatternPos posB = lineAtlas->getDashPosition(properties.dash_array.to, layout.cap == CapType::Round);
+ lineAtlas->bind();
float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0 * id.overscaling;
float scaleXA = patternratio / posA.width / properties.dash_line_width / properties.dash_array.fromScale;
@@ -81,14 +81,14 @@ 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 * state.getPixelRatio()) / 2;
+ linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * state.getPixelRatio()) / 2;
linesdfShader->u_mix = properties.dash_array.t;
bucket.drawLineSDF(*linesdfShader);
} else if (properties.image.from.size()) {
- SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true);
- SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true);
+ SpriteAtlasPosition imagePosA = spriteAtlas->getPosition(properties.image.from, true);
+ SpriteAtlasPosition imagePosB = spriteAtlas->getPosition(properties.image.to, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z) * id.overscaling;
@@ -110,7 +110,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
linepatternShader->u_opacity = properties.opacity;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
- spriteAtlas.bind(true);
+ spriteAtlas->bind(true);
config.depthRange = { strata + strata_epsilon, 1.0f }; // may or may not matter
bucket.drawLinePatterns(*linepatternShader);
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index dea6b8a6e6..4f4999b3e2 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -162,7 +162,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
const float fontSize = properties.icon.size != 0 ? properties.icon.size : layout.icon.max_size;
const float fontScale = fontSize / 1.0f;
- spriteAtlas.bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
+ spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
if (sdf) {
renderSDF(bucket,
@@ -171,7 +171,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
layout.icon,
properties.icon,
1.0f,
- {{ float(spriteAtlas.getWidth()) / 4.0f, float(spriteAtlas.getHeight()) / 4.0f }},
+ {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }},
*sdfIconShader,
&SymbolBucket::drawIcons);
} else {
@@ -189,7 +189,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
useProgram(iconShader->program);
iconShader->u_matrix = vtxMatrix;
iconShader->u_exmatrix = exMatrix;
- iconShader->u_texsize = {{ float(spriteAtlas.getWidth()) / 4.0f, float(spriteAtlas.getHeight()) / 4.0f }};
+ iconShader->u_texsize = {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }};
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / layout.icon.max_size) / std::log(2);
@@ -207,7 +207,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
}
if (bucket.hasTextData()) {
- glyphAtlas.bind();
+ glyphAtlas->bind();
renderSDF(bucket,
id,
@@ -215,7 +215,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
layout.text,
properties.text,
24.0f,
- {{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }},
+ {{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }},
*sdfGlyphShader,
&SymbolBucket::drawGlyphs);
}
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 0acf66eb56..8999af3c7f 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -1,9 +1,13 @@
#include <mbgl/style/style.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/map/source.hpp>
+#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_parser.hpp>
#include <mbgl/style/style_bucket.hpp>
+#include <mbgl/geometry/glyph_atlas.hpp>
+#include <mbgl/geometry/sprite_atlas.hpp>
+#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/uv_detail.hpp>
#include <mbgl/platform/log.hpp>
@@ -15,15 +19,77 @@
namespace mbgl {
-Style::Style()
- : mtx(std::make_unique<uv::rwlock>()),
+Style::Style(const std::string& data, const std::string&,
+ uv_loop_t* loop, Environment& env)
+ : glyphStore(std::make_unique<GlyphStore>(loop, env)),
+ glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)),
+ spriteAtlas(std::make_unique<SpriteAtlas>(512, 512)),
+ lineAtlas(std::make_unique<LineAtlas>(512, 512)),
+ mtx(std::make_unique<uv::rwlock>()),
workers(4) {
+
+ rapidjson::Document doc;
+ doc.Parse<0>((const char *const)data.c_str());
+ if (doc.HasParseError()) {
+ Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", doc.GetErrorOffset(), doc.GetParseError());
+ return;
+ }
+
+ StyleParser parser;
+ parser.parse(doc);
+
+ sources = parser.getSources();
+ layers = parser.getLayers();
+
+ spriteURL = parser.getSprite();
+ glyphStore->setURL(parser.getGlyphURL());
+
+ for (const auto& source : sources) {
+ source->setObserver(this);
+ source->load();
+ }
+
+ glyphStore->setObserver(this);
}
-// Note: This constructor is seemingly empty, but we need to declare it anyway
-// because this file includes uv_detail.hpp, which has the declarations necessary
-// for deleting the std::unique_ptr<uv::rwlock>.
-Style::~Style() {}
+Style::~Style() {
+ for (const auto& source : sources) {
+ source->setObserver(nullptr);
+ }
+
+ glyphStore->setObserver(nullptr);
+
+ if (sprite) {
+ sprite->setObserver(nullptr);
+ }
+}
+
+void Style::update(MapData& data,
+ const TransformState& transform,
+ TexturePool& texturePool) {
+ const float pixelRatio = transform.getPixelRatio();
+ if (!sprite || !sprite->hasPixelRatio(pixelRatio)) {
+ sprite = std::make_unique<Sprite>(spriteURL, pixelRatio);
+ sprite->setObserver(this);
+
+ spriteAtlas->resize(pixelRatio);
+ spriteAtlas->setSprite(sprite);
+ }
+
+ bool allTilesUpdated = true;
+ for (const auto& source : sources) {
+ if (!source->update(data, transform, *this, *glyphAtlas, *glyphStore,
+ *spriteAtlas, sprite, texturePool, shouldReparsePartialTiles)) {
+ allTilesUpdated = false;
+ }
+ }
+
+ // We can only stop updating "partial" tiles when all of them
+ // were notified of the arrival of the new resources.
+ if (allTilesUpdated) {
+ shouldReparsePartialTiles = false;
+ }
+}
void Style::cascade(const std::vector<std::string>& classes) {
TimePoint now = Clock::now();
@@ -50,10 +116,6 @@ void Style::recalculate(float z, TimePoint now) {
}
}
-const std::string &Style::getSpriteURL() const {
- return sprite_url;
-}
-
void Style::setDefaultTransitionDuration(Duration duration) {
defaultTransition.duration = duration;
}
@@ -67,44 +129,89 @@ bool Style::hasTransitions() const {
return false;
}
-void Style::loadJSON(const uint8_t *const data) {
- uv::writelock lock(mtx);
+bool Style::isLoaded() const {
+ for (const auto& source : sources) {
+ if (!source->isLoaded()) {
+ return false;
+ }
+ }
- rapidjson::Document doc;
- doc.Parse<0>((const char *const)data);
- if (doc.HasParseError()) {
- Log::Error(Event::ParseStyle, "Error parsing style JSON at %i: %s", doc.GetErrorOffset(), doc.GetParseError());
- return;
+ if (sprite && !sprite->isLoaded()) {
+ return false;
}
- StyleParser parser;
- parser.parse(doc);
+ return true;
+}
- sources = parser.getSources();
- layers = parser.getLayers();
- sprite_url = parser.getSprite();
- glyph_url = parser.getGlyphURL();
- loaded = true;
+void Style::setObserver(Observer* observer_) {
+ assert(Environment::currentlyOn(ThreadType::Map));
+ assert(!observer);
+
+ observer = observer_;
}
-bool Style::isLoaded() const {
- // TODO: move loading into Style
- if (!loaded) {
- return false;
+void Style::onGlyphRangeLoaded() {
+ shouldReparsePartialTiles = true;
+
+ emitTileDataChanged();
+}
+
+void Style::onGlyphRangeLoadingFailed(std::exception_ptr error) {
+ emitResourceLoadingFailed(error);
+}
+
+void Style::onSourceLoaded() {
+ emitTileDataChanged();
+}
+
+void Style::onSourceLoadingFailed(std::exception_ptr error) {
+ emitResourceLoadingFailed(error);
+}
+
+void Style::onTileLoaded(bool isNewTile) {
+ if (isNewTile) {
+ shouldReparsePartialTiles = true;
}
- for (const auto& source : sources) {
- if (!source->isLoaded()) {
- return false;
- }
+ emitTileDataChanged();
+}
+
+void Style::onTileLoadingFailed(std::exception_ptr error) {
+ emitResourceLoadingFailed(error);
+}
+
+void Style::onSpriteLoaded() {
+ shouldReparsePartialTiles = true;
+
+ emitTileDataChanged();
+}
+
+void Style::onSpriteLoadingFailed(std::exception_ptr error) {
+ emitResourceLoadingFailed(error);
+}
+
+void Style::emitTileDataChanged() {
+ assert(Environment::currentlyOn(ThreadType::Map));
+
+ if (observer) {
+ observer->onTileDataChanged();
}
+}
- // TODO: move sprite into Style
-// if (sprite && !sprite.isLoaded()) {
-// return false;
-// }
+void Style::emitResourceLoadingFailed(std::exception_ptr error) {
+ assert(Environment::currentlyOn(ThreadType::Map));
- return true;
+ try {
+ if (error) {
+ std::rethrow_exception(error);
+ }
+ } catch(const std::exception& e) {
+ Log::Error(Event::Style, e.what());
+ }
+
+ if (observer) {
+ observer->onResourceLoadingFailed(error);
+ }
}
}
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 42d7b0b9a0..c70f019c43 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -4,6 +4,10 @@
#include <mbgl/style/property_transition.hpp>
#include <mbgl/style/zoom_history.hpp>
+#include <mbgl/map/source.hpp>
+#include <mbgl/map/sprite.hpp>
+#include <mbgl/text/glyph_store.hpp>
+
#include <mbgl/util/uv.hpp>
#include <mbgl/util/ptr.hpp>
#include <mbgl/util/noncopyable.hpp>
@@ -16,33 +20,77 @@
namespace mbgl {
-class Source;
+class Environment;
+class GlyphAtlas;
+class GlyphStore;
+class SpriteAtlas;
+class LineAtlas;
class StyleLayer;
-class Style : public util::noncopyable {
+class Style : public GlyphStore::Observer,
+ public Source::Observer,
+ public Sprite::Observer,
+ public util::noncopyable {
public:
- Style();
+ Style(const std::string& data,
+ const std::string& base,
+ uv_loop_t*, Environment&);
~Style();
- void loadJSON(const uint8_t *const data);
+ class Observer {
+ public:
+ virtual ~Observer() = default;
+
+ virtual void onTileDataChanged() = 0;
+ virtual void onResourceLoadingFailed(std::exception_ptr error) = 0;
+ };
+
+ void setObserver(Observer*);
+
bool isLoaded() const;
+ // Fetch the tiles needed by the current viewport and emit a signal when
+ // a tile is ready so observers can render the tile.
+ void update(MapData&, const TransformState&, TexturePool&);
+
void cascade(const std::vector<std::string>&);
void recalculate(float z, TimePoint now);
void setDefaultTransitionDuration(Duration);
bool hasTransitions() const;
- const std::string &getSpriteURL() const;
+ std::unique_ptr<GlyphStore> glyphStore;
+ std::unique_ptr<GlyphAtlas> glyphAtlas;
+ util::ptr<Sprite> sprite;
+ std::unique_ptr<SpriteAtlas> spriteAtlas;
+ std::unique_ptr<LineAtlas> lineAtlas;
std::vector<util::ptr<Source>> sources;
std::vector<util::ptr<StyleLayer>> layers;
- std::string glyph_url;
- std::string base;
private:
- bool loaded = false;
- std::string sprite_url;
+ // GlyphStore::Observer implementation.
+ void onGlyphRangeLoaded() override;
+ void onGlyphRangeLoadingFailed(std::exception_ptr error) override;
+
+ // Source::Observer implementation.
+ void onSourceLoaded() override;
+ void onSourceLoadingFailed(std::exception_ptr error) override;
+ void onTileLoaded(bool isNewTile) override;
+ void onTileLoadingFailed(std::exception_ptr error) override;
+
+ // Sprite::Observer implementation.
+ void onSpriteLoaded() override;
+ void onSpriteLoadingFailed(std::exception_ptr error) override;
+
+ void emitTileDataChanged();
+ void emitResourceLoadingFailed(std::exception_ptr error);
+
+ bool shouldReparsePartialTiles = false;
+
+ Observer* observer = nullptr;
+
+ std::string spriteURL;
PropertyTransition defaultTransition;
std::unique_ptr<uv::rwlock> mtx;
ZoomHistory zoomHistory;
diff --git a/test/ios/MetricsTests.m b/test/ios/MetricsTests.m
index 758cf1f5be..7c71ee6739 100644
--- a/test/ios/MetricsTests.m
+++ b/test/ios/MetricsTests.m
@@ -8,6 +8,9 @@
#import "MapboxGL.h"
#import "OHHTTPStubs.h"
+const NSUInteger MGLMaximumEventsPerFlush = 20;
+const NSTimeInterval MGLFlushInterval = 60;
+
@interface MGLMapboxEvents (Testing)
- (NSString *)appBundleId;
@@ -18,9 +21,6 @@
- (NSMutableArray *)eventQueue;
- (void)postEvents:(NSArray *)events;
- (NSTimer *)timer;
-- (NSUInteger)flushAt;
-- (NSTimeInterval)flushAfter;
-- (void)setFlushAfter:(NSTimeInterval)newFlushAfter;
- (void)flush;
- (void)startTimer;
@@ -28,15 +28,12 @@
@interface MetricsTests : KIFTestCase
-@property (nonatomic) NSTimeInterval defaultFlushAfter;
-
@end
@implementation MetricsTests
- (void)beforeAll {
[tester acknowledgeSystemAlert];
- self.defaultFlushAfter = [[MGLMapboxEvents sharedManager] flushAfter];
}
- (void)beforeEach {
@@ -44,8 +41,6 @@
[MGLMapboxEvents resumeMetricsCollection];
[MGLAccountManager setAccessToken:@"pk.eyJ1IjoianVzdGluIiwiYSI6IlpDbUJLSUEifQ.4mG8vhelFMju6HpIY-Hi5A"];
-
- [[MGLMapboxEvents sharedManager] setFlushAfter:self.defaultFlushAfter];
}
- (void)afterEach {
@@ -76,7 +71,6 @@
- (void)testFlushAtThreshold {
NSUInteger startCount = [[[MGLMapboxEvents sharedManager] eventQueue] count];
- NSUInteger flushAt = [[MGLMapboxEvents sharedManager] flushAt];
XCTestExpectation *queueItemsExpectation = [self expectationWithDescription:@"queue should contain events"];
@@ -89,7 +83,7 @@
}
});
- for (NSUInteger i = 0; i < (flushAt - startCount - 1); i++) {
+ for (NSUInteger i = 0; i < (MGLMaximumEventsPerFlush - startCount - 1); i++) {
[self pushFakeEvent];
}
@@ -146,8 +140,6 @@
[self waitForExpectationsWithTimeout:1.0 handler:nil];
- [[MGLMapboxEvents sharedManager] setFlushAfter:5];
-
id eventsMock = [OCMockObject partialMockForObject:[MGLMapboxEvents sharedManager]];
[[[eventsMock expect] andForwardToRealObject] startTimer];
[self pushFakeEvent];
@@ -155,7 +147,7 @@
XCTAssertEqual([[[MGLMapboxEvents sharedManager] eventQueue] count], 1);
XCTAssertNotNil([[MGLMapboxEvents sharedManager] timer]);
- XCTAssertEqual([[MGLMapboxEvents sharedManager] flushAfter], [[[MGLMapboxEvents sharedManager] timer] timeInterval]);
+ XCTAssertEqual(MGLFlushInterval, [[[MGLMapboxEvents sharedManager] timer] timeInterval]);
}
- (void)testTimerFiresFlush {
@@ -174,11 +166,10 @@
[self waitForExpectationsWithTimeout:1.0 handler:nil];
- [[MGLMapboxEvents sharedManager] setFlushAfter:5];
[self pushFakeEvent];
id eventsMock = [OCMockObject partialMockForObject:[MGLMapboxEvents sharedManager]];
[[eventsMock expect] flush];
- [eventsMock verifyWithDelay:[[MGLMapboxEvents sharedManager] flushAfter]];
+ [eventsMock verifyWithDelay:MGLFlushInterval];
}
- (void)testFlushPostsEvents {
diff --git a/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme b/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme
index 911f949fa0..0008282f89 100644
--- a/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme
+++ b/test/ios/ios-tests.xcodeproj/xcshareddata/xcschemes/Mapbox GL Tests.xcscheme
@@ -55,6 +55,15 @@
<Test
Identifier = "MapViewTests/testDelegateRegionWillChange">
</Test>
+ <Test
+ Identifier = "MetricsTests/testFlushPostsEvents">
+ </Test>
+ <Test
+ Identifier = "MetricsTests/testPostEventsNetworkRequest">
+ </Test>
+ <Test
+ Identifier = "MetricsTests/testTimerFiresFlush">
+ </Test>
</SkippedTests>
</TestableReference>
</Testables>
diff --git a/test/miscellaneous/style_parser.cpp b/test/miscellaneous/style_parser.cpp
index f5b9bb7e63..7a38ba054d 100644
--- a/test/miscellaneous/style_parser.cpp
+++ b/test/miscellaneous/style_parser.cpp
@@ -1,6 +1,6 @@
#include "../fixtures/util.hpp"
-#include <mbgl/style/style.hpp>
+#include <mbgl/style/style_parser.hpp>
#include <mbgl/util/io.hpp>
#include <rapidjson/document.h>
@@ -22,27 +22,23 @@ class StyleParserTest : public ::testing::TestWithParam<std::string> {};
TEST_P(StyleParserTest, ParseStyle) {
const std::string &base = "test/fixtures/style_parser/" + GetParam();
- const std::string style_path = base + ".style.json";
- const std::string info = util::read_file(base + ".info.json");
+ rapidjson::Document infoDoc;
+ infoDoc.Parse<0>(util::read_file(base + ".info.json").c_str());
+ ASSERT_FALSE(infoDoc.HasParseError());
+ ASSERT_TRUE(infoDoc.IsObject());
- // Parse settings.
- rapidjson::Document doc;
- doc.Parse<0>((const char *const)info.c_str());
- ASSERT_FALSE(doc.HasParseError());
- ASSERT_TRUE(doc.IsObject());
-
- std::ifstream stylefile(style_path);
- ASSERT_TRUE(stylefile.good());
- std::stringstream stylejson;
- stylejson << stylefile.rdbuf();
+ rapidjson::Document styleDoc;
+ styleDoc.Parse<0>(util::read_file(base + ".style.json").c_str());
+ ASSERT_FALSE(styleDoc.HasParseError());
+ ASSERT_TRUE(styleDoc.IsObject());
FixtureLogObserver* observer = new FixtureLogObserver();
Log::setObserver(std::unique_ptr<Log::Observer>(observer));
- Style style;
- style.loadJSON((const uint8_t *)stylejson.str().c_str());
+ StyleParser parser;
+ parser.parse(styleDoc);
- for (auto it = doc.MemberBegin(), end = doc.MemberEnd(); it != end; it++) {
+ for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) {
const std::string name { it->name.GetString(), it->name.GetStringLength() };
const rapidjson::Value &value = it->value;
ASSERT_EQ(true, value.IsObject());
diff --git a/test/resources/mock_file_source.cpp b/test/style/mock_file_source.cpp
index 42067a2a73..42067a2a73 100644
--- a/test/resources/mock_file_source.cpp
+++ b/test/style/mock_file_source.cpp
diff --git a/test/resources/mock_file_source.hpp b/test/style/mock_file_source.hpp
index bb9fb55a30..bb9fb55a30 100644
--- a/test/resources/mock_file_source.hpp
+++ b/test/style/mock_file_source.hpp
diff --git a/test/resources/mock_view.hpp b/test/style/mock_view.hpp
index 865cd2da55..865cd2da55 100644
--- a/test/resources/mock_view.hpp
+++ b/test/style/mock_view.hpp
diff --git a/test/resources/resource_loader.cpp b/test/style/resource_loading.cpp
index 7d57f47ee6..de3e6b812e 100644
--- a/test/resources/resource_loader.cpp
+++ b/test/style/resource_loading.cpp
@@ -3,14 +3,10 @@
#include "mock_file_source.hpp"
#include "mock_view.hpp"
-#include <mbgl/geometry/glyph_atlas.hpp>
-#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/map/environment.hpp>
#include <mbgl/map/map_data.hpp>
-#include <mbgl/map/resource_loader.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/style.hpp>
-#include <mbgl/text/glyph_store.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -21,7 +17,7 @@ using namespace mbgl;
namespace {
-class MockMapContext : public ResourceLoader::Observer {
+class MockMapContext : public Style::Observer {
public:
MockMapContext(uv_loop_t* loop,
View& view,
@@ -30,36 +26,19 @@ public:
: env_(fileSource),
envScope_(env_, ThreadType::Map, "Map"),
data_(view, MapMode::Still),
- glyphStore_(std::make_unique<GlyphStore>(loop, env_)),
- glyphAtlas_(std::make_unique<GlyphAtlas>(1024, 1024)),
- spriteAtlas_(std::make_unique<SpriteAtlas>(512, 512)),
- texturePool_(std::make_unique<TexturePool>()),
- style_(std::make_unique<Style>()),
- resourceLoader_(std::make_unique<ResourceLoader>()),
- asyncUpdate(std::make_unique<uv::async>(loop, [this] { update(); })),
callback_(callback) {
- asyncUpdate->unref();
data_.transform.resize(1000, 1000, 1.0, 1000, 1000);
data_.transform.setLatLngZoom({0, 0}, 16);
const std::string style = util::read_file("test/fixtures/resources/style.json");
- style_->loadJSON(reinterpret_cast<const uint8_t *>(style.c_str()));
-
- glyphStore_->setURL(style_->glyph_url);
-
- resourceLoader_->setGlyphStore(glyphStore_.get());
- resourceLoader_->setObserver(this);
- resourceLoader_->setStyle(style_.get());
+ style_ = std::make_unique<Style>(style, "", loop, env_),
+ style_->setObserver(this);
}
~MockMapContext() {
- resourceLoader_.reset();
style_.reset();
- texturePool_.reset();
- spriteAtlas_.reset();
- glyphAtlas_.reset();
- glyphStore_.reset();
+ env_.performCleanup();
}
void update() {
@@ -69,19 +48,16 @@ public:
data_.transform.updateTransitions(now);
transformState_ = data_.transform.currentState();
-
- resourceLoader_->update(
- data_, transformState_, *glyphAtlas_, *spriteAtlas_, *texturePool_);
+ style_->update(data_, transformState_, texturePool_);
}
- // ResourceLoader::Observer implementation.
+ // Style::Observer implementation.
void onTileDataChanged() override {
- util::ptr<Sprite> sprite = resourceLoader_->getSprite();
- if (sprite && sprite->isLoaded() && style_->isLoaded()) {
+ update();
+
+ if (style_->isLoaded()) {
callback_(nullptr);
}
-
- asyncUpdate->send();
};
void onResourceLoadingFailed(std::exception_ptr error) override {
@@ -94,15 +70,9 @@ private:
MapData data_;
TransformState transformState_;
+ TexturePool texturePool_;
- std::unique_ptr<GlyphStore> glyphStore_;
- std::unique_ptr<GlyphAtlas> glyphAtlas_;
- std::unique_ptr<SpriteAtlas> spriteAtlas_;
- std::unique_ptr<TexturePool> texturePool_;
std::unique_ptr<Style> style_;
- std::unique_ptr<ResourceLoader> resourceLoader_;
-
- std::unique_ptr<uv::async> asyncUpdate;
std::function<void(std::exception_ptr error)> callback_;
};
@@ -118,7 +88,13 @@ void runTestCase(MockFileSource::Type type,
FixtureLogObserver* log = new FixtureLogObserver();
Log::setObserver(std::unique_ptr<Log::Observer>(log));
- auto callback = [&loop, &param](std::exception_ptr error) {
+ auto callback = [type, &loop, &param](std::exception_ptr error) {
+ if (type == MockFileSource::Success) {
+ EXPECT_TRUE(error == nullptr);
+ } else {
+ EXPECT_TRUE(error != nullptr);
+ }
+
try {
if (error) {
std::rethrow_exception(error);
@@ -150,7 +126,7 @@ void runTestCase(MockFileSource::Type type,
const FixtureLogObserver::LogMessage logMessage {
EventSeverity::Error,
- Event::ResourceLoader,
+ Event::Style,
int64_t(-1),
message,
};
@@ -167,21 +143,21 @@ void runTestCase(MockFileSource::Type type,
}
-class ResourceLoaderTest : public ::testing::TestWithParam<std::string> {
+class ResourceLoading : public ::testing::TestWithParam<std::string> {
};
-TEST_P(ResourceLoaderTest, Success) {
+TEST_P(ResourceLoading, Success) {
runTestCase(MockFileSource::Success, GetParam(), std::string());
}
-TEST_P(ResourceLoaderTest, RequestFail) {
+TEST_P(ResourceLoading, RequestFail) {
std::stringstream message;
message << "Failed to load [test/fixtures/resources/" << GetParam() << "]: Failed by the test case";
runTestCase(MockFileSource::RequestFail, GetParam(), message.str());
}
-TEST_P(ResourceLoaderTest, RequestWithCorruptedData) {
+TEST_P(ResourceLoading, RequestWithCorruptedData) {
const std::string param(GetParam());
std::stringstream message;
@@ -200,5 +176,5 @@ TEST_P(ResourceLoaderTest, RequestWithCorruptedData) {
runTestCase(MockFileSource::RequestWithCorruptedData, GetParam(), message.str());
}
-INSTANTIATE_TEST_CASE_P(ResourceLoader, ResourceLoaderTest,
+INSTANTIATE_TEST_CASE_P(Style, ResourceLoading,
::testing::Values("source.json", "sprite.json", "sprite.png", "vector.pbf", "glyphs.pbf"));
diff --git a/test/test.gypi b/test/test.gypi
index 24582df992..0e14ac0835 100644
--- a/test/test.gypi
+++ b/test/test.gypi
@@ -58,11 +58,6 @@
'miscellaneous/variant.cpp',
'miscellaneous/worker.cpp',
- 'resources/mock_file_source.cpp',
- 'resources/mock_file_source.hpp',
- 'resources/mock_view.hpp',
- 'resources/resource_loader.cpp',
-
'storage/storage.hpp',
'storage/storage.cpp',
'storage/cache_response.cpp',
@@ -78,6 +73,11 @@
'storage/http_load.cpp',
'storage/http_other_loop.cpp',
'storage/http_reading.cpp',
+
+ 'style/mock_file_source.cpp',
+ 'style/mock_file_source.hpp',
+ 'style/mock_view.hpp',
+ 'style/resource_loading.cpp',
],
'libraries': [
'<@(uv_static_libs)',