From 028abaab00f2ff3a19c67366c3a9f8c803e27423 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 22 Sep 2015 16:58:38 -0700 Subject: [PATCH] Ensure that LiveTileData can be reparsed Annotation tiles may become partially parsed just like regular tiles, for example if a point annotation is added to the map before the style's sprite has been loaded. In such cases, they need to be reparsed or the annotation will not be rendered. Previously, the code path for reparsing would be short-circuited by a dynamic_cast followed by a null check. This commit removes that case and adds (back) a virtual reparse method to the TileData interface. --- .gitignore | 1 + src/mbgl/map/live_tile_data.cpp | 19 +++++++++++++++++-- src/mbgl/map/live_tile_data.hpp | 4 ++++ src/mbgl/map/source.cpp | 8 +++----- src/mbgl/map/tile_data.hpp | 1 + src/mbgl/map/vector_tile_data.hpp | 2 +- test/api/annotations.cpp | 28 +++++++++++++--------------- test/fixtures/api/empty.json | 6 ++++++ test/output/.gitkeep | 0 9 files changed, 46 insertions(+), 23 deletions(-) create mode 100644 test/fixtures/api/empty.json create mode 100644 test/output/.gitkeep diff --git a/.gitignore b/.gitignore index bd6707ba9..4d0b4074c 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ /test/fixtures/api/1.png /test/fixtures/api/2.png /test/fixtures/database/*.db +/test/output /include/mbgl/shader/shaders.hpp /src/shader/shaders_gl.cpp /src/shader/shaders_gles2.cpp diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index 0b73b52f3..fbb9c10de 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -13,7 +13,7 @@ using namespace mbgl; LiveTileData::LiveTileData(const TileID& id_, - const LiveTile* tile, + const LiveTile* tile_, Style& style_, const SourceInfo& source_, std::function callback) @@ -25,7 +25,8 @@ LiveTileData::LiveTileData(const TileID& id_, style_, style_.layers, state, - std::make_unique(0, 0, false)) { + std::make_unique(0, 0, false)), + tile(tile_) { state = State::loaded; if (!tile) { @@ -33,7 +34,19 @@ LiveTileData::LiveTileData(const TileID& id_, return; } + reparse(callback); +} + +bool LiveTileData::reparse(std::function callback) { + if (parsing || (state != State::loaded && state != State::partial)) { + return false; + } + + parsing = true; + workRequest = worker.parseLiveTile(tileWorker, *tile, [this, callback] (TileParseResult result) { + parsing = false; + if (result.is()) { state = result.get(); } else { @@ -43,6 +56,8 @@ LiveTileData::LiveTileData(const TileID& id_, callback(); }); + + return true; } LiveTileData::~LiveTileData() { diff --git a/src/mbgl/map/live_tile_data.hpp b/src/mbgl/map/live_tile_data.hpp index 5c4220fd6..c6507bbc3 100644 --- a/src/mbgl/map/live_tile_data.hpp +++ b/src/mbgl/map/live_tile_data.hpp @@ -20,6 +20,8 @@ public: std::function callback); ~LiveTileData(); + bool reparse(std::function callback) override; + void cancel() override; Bucket* getBucket(const StyleLayer&) override; @@ -27,6 +29,8 @@ private: Worker& worker; TileWorker tileWorker; std::unique_ptr workRequest; + bool parsing = false; + const LiveTile* tile; }; } diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 5899fea1e..572973b79 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -234,15 +234,13 @@ bool Source::handlePartialTile(const TileID& id, Worker&) { return true; } - // Note: this uses a raw pointer; we don't want the callback binding to have a - // shared pointer. - VectorTileData* data = dynamic_cast(it->second.lock().get()); + auto data = it->second.lock(); if (!data) { return true; } - return data->reparse([this, data]() { - emitTileLoaded(false); + return data->reparse([this]() { + emitTileLoaded(false); }); } diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp index 047ccd5cd..fcbf25fb6 100644 --- a/src/mbgl/map/tile_data.hpp +++ b/src/mbgl/map/tile_data.hpp @@ -72,6 +72,7 @@ public: virtual Bucket* getBucket(const StyleLayer&) = 0; + virtual bool reparse(std::function) { return true; } virtual void redoPlacement(float, float, bool) {} bool isReady() const { diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 4db0cbe00..c004e804b 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -28,7 +28,7 @@ public: void request(float pixelRatio, const std::function& callback); - bool reparse(std::function callback); + bool reparse(std::function callback) override; void redoPlacement(float angle, float pitch, bool collisionDebug) override; diff --git a/test/api/annotations.cpp b/test/api/annotations.cpp index 33374d438..39862b106 100644 --- a/test/api/annotations.cpp +++ b/test/api/annotations.cpp @@ -1,5 +1,3 @@ -#include "../fixtures/fixture_log_observer.hpp" -#include "../fixtures/mock_file_source.hpp" #include "../fixtures/util.hpp" #include @@ -7,30 +5,30 @@ #include #include #include +#include +#include +#include #include #include -TEST(API, PointAnnotation) { +TEST(Annotations, PointAnnotation) { using namespace mbgl; auto display = std::make_shared(); HeadlessView view(display, 1); - - MockFileSource fileSource(MockFileSource::Success, ""); + DefaultFileSource fileSource(nullptr); Map map(view, fileSource, MapMode::Still); - map.setStyleURL("test/fixtures/resources/style.json"); + map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), ""); + map.addPointAnnotation(PointAnnotation({ 0, 0 }, "default_marker")); - std::vector points; - points.emplace_back(PointAnnotation({ 50.0, 50.0 }, "default_marker")); - - map.addPointAnnotations(points); - - std::promise promise; - map.renderStill([&promise](std::exception_ptr, std::unique_ptr) { - promise.set_value(true); + std::promise> promise; + map.renderStill([&promise](std::exception_ptr, std::unique_ptr image) { + promise.set_value(std::move(image)); }); - promise.get_future().get(); + auto result = promise.get_future().get(); + const std::string png = util::compress_png(result->width, result->height, result->pixels.get()); + util::write_file("test/output/point_annotation.png", png); } diff --git a/test/fixtures/api/empty.json b/test/fixtures/api/empty.json new file mode 100644 index 000000000..acc8a630c --- /dev/null +++ b/test/fixtures/api/empty.json @@ -0,0 +1,6 @@ +{ + "version": 8, + "sources": {}, + "layers": [], + "sprite": "asset://TEST_DATA/fixtures/resources/sprite" +} diff --git a/test/output/.gitkeep b/test/output/.gitkeep new file mode 100644 index 000000000..e69de29bb