diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index 548c837add4..a761d28ab55 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -167,9 +167,7 @@ TileData::State Source::addTile(const TileID& id, const StyleUpdateParameters& p return state; } - auto pos = tiles.emplace(id, std::make_unique(id)); - - Tile& new_tile = *pos.first->second; + auto newTile = std::make_unique(id); // We couldn't find the tile in the list. Create a new one. // Try to find the associated TileData object. @@ -178,19 +176,19 @@ TileData::State Source::addTile(const TileID& id, const StyleUpdateParameters& p auto it = tileDataMap.find(normalized_id); if (it != tileDataMap.end()) { // Create a shared_ptr handle. Note that this might be empty! - new_tile.data = it->second.lock(); + newTile->data = it->second.lock(); } - if (new_tile.data && new_tile.data->getState() == TileData::State::obsolete) { + if (newTile->data && newTile->data->getState() == TileData::State::obsolete) { // Do not consider the tile if it's already obsolete. - new_tile.data.reset(); + newTile->data.reset(); } - if (!new_tile.data) { - new_tile.data = cache.get(normalized_id.to_uint64()); + if (!newTile->data) { + newTile->data = cache.get(normalized_id.to_uint64()); } - if (!new_tile.data) { + if (!newTile->data) { auto callback = std::bind(&Source::tileLoadingCompleteCallback, this, normalized_id, parameters.transformState, parameters.debugOptions & MapDebugOptions::Collision); // If we don't find working tile data, we're just going to load it. @@ -201,7 +199,7 @@ TileData::State Source::addTile(const TileID& id, const StyleUpdateParameters& p parameters.worker); tileData->request(parameters.pixelRatio, callback); - new_tile.data = tileData; + newTile->data = tileData; } else { std::unique_ptr monitor; @@ -210,20 +208,23 @@ TileData::State Source::addTile(const TileID& id, const StyleUpdateParameters& p } else if (info.type == SourceType::Annotations) { monitor = std::make_unique(normalized_id, parameters.data); } else { - throw std::runtime_error("source type not implemented"); + Log::Warning(Event::Style, "Source type '%s' is not implemented", SourceTypeClass(info.type).c_str()); + return TileData::State::invalid; } - new_tile.data = std::make_shared(normalized_id, + newTile->data = std::make_shared(normalized_id, std::move(monitor), info.source_id, parameters.style, callback); } - tileDataMap.emplace(new_tile.data->id, new_tile.data); + tileDataMap.emplace(newTile->data->id, newTile->data); } - return new_tile.data->getState(); + const auto newState = newTile->data->getState(); + tiles.emplace(id, std::move(newTile)); + return newState; } double Source::getZoom(const TransformState& state) const { diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index d029f633af9..483d096a7f1 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -8,6 +8,9 @@ #include +#include +#include + #include namespace mbgl { @@ -84,6 +87,11 @@ void StyleParser::parseSources(const JSVal& value) { continue; } break; + case SourceType::GeoJSON: + if (!parseGeoJSONSource(*source, sourceVal)) { + continue; + } + break; default: Log::Warning(Event::ParseStyle, "source type %s is not supported", SourceTypeClass(source->info.type).c_str()); } @@ -150,6 +158,29 @@ bool StyleParser::parseRasterSource(Source& source, const JSVal& sourceVal) { return true; } +bool StyleParser::parseGeoJSONSource(Source& source, const JSVal& sourceVal) { + if (!sourceVal.HasMember("data")) { + Log::Warning(Event::ParseStyle, "GeoJSON source must have a data value"); + return false; + } + + const JSVal& dataVal = sourceVal["data"]; + if (dataVal.IsString()) { + // We need to load an external GeoJSON file + source.info.url = { dataVal.GetString(), dataVal.GetStringLength() }; + + } else if (dataVal.IsObject()) { + // We need to parse dataVal as a GeoJSON object + auto geojsonvt = std::make_unique(mapbox::geojsonvt::Convert::convert(dataVal, 0)); + // TODO + } else { + Log::Warning(Event::ParseStyle, "GeoJSON data must be a URL or an object"); + return false; + } + + return true; +} + void StyleParser::parseLayers(const JSVal& value) { std::vector ids; diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index 2307517e37d..898f39bd01d 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -35,6 +35,7 @@ class StyleParser { void parseSources(const JSVal&); bool parseVectorSource(Source&, const JSVal&); bool parseRasterSource(Source&, const JSVal&); + bool parseGeoJSONSource(Source&, const JSVal&); void parseLayers(const JSVal&); void parseLayer(const std::string& id, const JSVal&, std::unique_ptr&); void parseVisibility(StyleLayer&, const JSVal& value); diff --git a/test/fixtures/style_parser/geojson-data-inline.info.json b/test/fixtures/style_parser/geojson-data-inline.info.json new file mode 100644 index 00000000000..9c25a2f4888 --- /dev/null +++ b/test/fixtures/style_parser/geojson-data-inline.info.json @@ -0,0 +1,6 @@ +{ + "default": { + "log": [ + ] + } +} diff --git a/test/fixtures/style_parser/geojson-data-inline.style.json b/test/fixtures/style_parser/geojson-data-inline.style.json new file mode 100644 index 00000000000..fc4fe97c784 --- /dev/null +++ b/test/fixtures/style_parser/geojson-data-inline.style.json @@ -0,0 +1,9 @@ +{ + "version": 8, + "sources": { + "mapbox": { + "type": "geojson", + "data": { "type": "Feature", "geometry": { "type": "Point", "coordinates": [100.0, 0.0] } } + } + } +} diff --git a/test/fixtures/style_parser/geojson-data-url.info.json b/test/fixtures/style_parser/geojson-data-url.info.json new file mode 100644 index 00000000000..9c25a2f4888 --- /dev/null +++ b/test/fixtures/style_parser/geojson-data-url.info.json @@ -0,0 +1,6 @@ +{ + "default": { + "log": [ + ] + } +} diff --git a/test/fixtures/style_parser/geojson-data-url.style.json b/test/fixtures/style_parser/geojson-data-url.style.json new file mode 100644 index 00000000000..a5e1c99628f --- /dev/null +++ b/test/fixtures/style_parser/geojson-data-url.style.json @@ -0,0 +1,9 @@ +{ + "version": 8, + "sources": { + "mapbox": { + "type": "geojson", + "data": "asset://TEST_DATA/fixtures/geojson/point.json" + } + } +} diff --git a/test/fixtures/style_parser/geojson-invalid-data.info.json b/test/fixtures/style_parser/geojson-invalid-data.info.json new file mode 100644 index 00000000000..86f1ef6edda --- /dev/null +++ b/test/fixtures/style_parser/geojson-invalid-data.info.json @@ -0,0 +1,7 @@ +{ + "default": { + "log": [ + [1, "WARNING", "ParseStyle", "GeoJSON data must be a URL or an object"] + ] + } +} diff --git a/test/fixtures/style_parser/geojson-invalid-data.style.json b/test/fixtures/style_parser/geojson-invalid-data.style.json new file mode 100644 index 00000000000..ca1b275967b --- /dev/null +++ b/test/fixtures/style_parser/geojson-invalid-data.style.json @@ -0,0 +1,9 @@ +{ + "version": 8, + "sources": { + "mapbox": { + "type": "geojson", + "data": 24 + } + } +} diff --git a/test/fixtures/style_parser/geojson-missing-data.info.json b/test/fixtures/style_parser/geojson-missing-data.info.json new file mode 100644 index 00000000000..594d01d19df --- /dev/null +++ b/test/fixtures/style_parser/geojson-missing-data.info.json @@ -0,0 +1,7 @@ +{ + "default": { + "log": [ + [1, "WARNING", "ParseStyle", "GeoJSON source must have a data value"] + ] + } +} diff --git a/test/fixtures/style_parser/geojson-missing-data.style.json b/test/fixtures/style_parser/geojson-missing-data.style.json new file mode 100644 index 00000000000..8af64b01760 --- /dev/null +++ b/test/fixtures/style_parser/geojson-missing-data.style.json @@ -0,0 +1,8 @@ +{ + "version": 8, + "sources": { + "mapbox": { + "type": "geojson" + } + } +}