diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp index a814e484f..19a6124da 100644 --- a/src/mbgl/map/source.cpp +++ b/src/mbgl/map/source.cpp @@ -28,6 +28,9 @@ #include #include +#include +#include + #include #include @@ -35,6 +38,84 @@ namespace mbgl { +namespace { + +void parse(const JSValue& value, std::vector& target, const char* name) { + if (!value.HasMember(name)) { + return; + } + + const JSValue& property = value[name]; + if (!property.IsArray()) { + return; + } + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) { + if (!property[i].IsString()) { + return; + } + } + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) { + target.emplace_back(std::string(property[i].GetString(), property[i].GetStringLength())); + } +} + +void parse(const JSValue& value, std::string& target, const char* name) { + if (!value.HasMember(name)) { + return; + } + + const JSValue& property = value[name]; + if (!property.IsString()) { + return; + } + + target = { property.GetString(), property.GetStringLength() }; +} + +void parse(const JSValue& value, uint16_t& target, const char* name) { + if (!value.HasMember(name)) { + return; + } + + const JSValue& property = value[name]; + if (!property.IsUint()) { + return; + } + + unsigned int uint = property.GetUint(); + if (uint > std::numeric_limits::max()) { + return; + } + + target = uint; +} + +template +void parse(const JSValue& value, std::array& target, const char* name) { + if (!value.HasMember(name)) { + return; + } + + const JSValue& property = value[name]; + if (!property.IsArray() || property.Size() != N) { + return; + } + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) { + if (!property[i].IsNumber()) { + return; + } + } + + for (rapidjson::SizeType i = 0; i < property.Size(); i++) { + target[i] = property[i].GetDouble(); + } +} + +} // end namespace + Source::Source() {} Source::~Source() = default; @@ -91,9 +172,9 @@ void Source::load() { } if (info.type == SourceType::Vector || info.type == SourceType::Raster) { - info.parseTileJSONProperties(d); + parseTileJSON(d); } else if (info.type == SourceType::GeoJSON) { - info.parseGeoJSON(d); + parseGeoJSON(d); } loaded = true; @@ -101,6 +182,28 @@ void Source::load() { }); } +void Source::parseTileJSON(const JSValue& value) { + parse(value, info.tiles, "tiles"); + parse(value, info.min_zoom, "minzoom"); + parse(value, info.max_zoom, "maxzoom"); + parse(value, info.attribution, "attribution"); + parse(value, info.center, "center"); + parse(value, info.bounds, "bounds"); +} + +void Source::parseGeoJSON(const JSValue& value) { + using namespace mapbox::geojsonvt; + + try { + geojsonvt = std::make_unique(Convert::convert(value, 0)); + } catch (const std::exception& ex) { + Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", ex.what()); + // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for + // tiles to load. + geojsonvt = std::make_unique(std::vector{}); + } +} + void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transform) { for (const auto& pair : tiles) { Tile &tile = *pair.second; @@ -217,7 +320,7 @@ 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 if (info.type == SourceType::GeoJSON) { - monitor = std::make_unique(info.geojsonvt.get(), normalized_id); + monitor = std::make_unique(geojsonvt.get(), normalized_id); } else { Log::Warning(Event::Style, "Source type '%s' is not implemented", SourceTypeClass(info.type).c_str()); return TileData::State::invalid; diff --git a/src/mbgl/map/source.hpp b/src/mbgl/map/source.hpp index 36613c205..8f6620d52 100644 --- a/src/mbgl/map/source.hpp +++ b/src/mbgl/map/source.hpp @@ -5,10 +5,17 @@ #include #include +#include #include #include +namespace mapbox { +namespace geojsonvt { +class GeoJSONVT; +} // namespace geojsonvt +} // namespace mapbox + namespace mbgl { class StyleUpdateParameters; @@ -35,6 +42,9 @@ public: Source(); ~Source(); + void parseTileJSON(const JSValue&); + void parseGeoJSON(const JSValue&); + bool loaded = false; void load(); bool isLoading() const; @@ -76,6 +86,8 @@ private: double getZoom(const TransformState &state) const; + std::unique_ptr geojsonvt; + // Stores the time when this source was most recently updated. TimePoint updated = TimePoint::min(); diff --git a/src/mbgl/map/source_info.cpp b/src/mbgl/map/source_info.cpp index 07346ea69..2980e3ec4 100644 --- a/src/mbgl/map/source_info.cpp +++ b/src/mbgl/map/source_info.cpp @@ -1,117 +1,11 @@ -#include #include +#include #include #include #include -#include -#include - namespace mbgl { -namespace { - -void parse(const JSValue& value, std::vector& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsArray()) { - return; - } - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) { - if (!property[i].IsString()) { - return; - } - } - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) { - target.emplace_back(std::string(property[i].GetString(), property[i].GetStringLength())); - } -} - -void parse(const JSValue& value, std::string& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsString()) { - return; - } - - target = { property.GetString(), property.GetStringLength() }; -} - -void parse(const JSValue& value, uint16_t& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsUint()) { - return; - } - - unsigned int uint = property.GetUint(); - if (uint > std::numeric_limits::max()) { - return; - } - - target = uint; -} - -template -void parse(const JSValue& value, std::array& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsArray() || property.Size() != N) { - return; - } - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) { - if (!property[i].IsNumber()) { - return; - } - } - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) { - target[i] = property[i].GetDouble(); - } -} - -} // end namespace - -// Destructor in implementation file because header only contains forward declarations. -SourceInfo::~SourceInfo() = default; - -void SourceInfo::parseTileJSONProperties(const JSValue& value) { - parse(value, tiles, "tiles"); - parse(value, min_zoom, "minzoom"); - parse(value, max_zoom, "maxzoom"); - parse(value, attribution, "attribution"); - parse(value, center, "center"); - parse(value, bounds, "bounds"); -} - -void SourceInfo::parseGeoJSON(const JSValue& value) { - using namespace mapbox::geojsonvt; - - try { - geojsonvt = std::make_unique(Convert::convert(value, 0)); - } catch (const std::exception& ex) { - Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", ex.what()); - // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for - // tiles to load. - geojsonvt = std::make_unique(std::vector{}); - } -} - std::string SourceInfo::tileURL(const TileID& id, float pixelRatio) const { std::string result = tiles.at(0); result = util::mapbox::normalizeTileURL(result, url, type); diff --git a/src/mbgl/map/source_info.hpp b/src/mbgl/map/source_info.hpp index 38fa411bc..6e52dc8c0 100644 --- a/src/mbgl/map/source_info.hpp +++ b/src/mbgl/map/source_info.hpp @@ -2,30 +2,19 @@ #define MBGL_MAP_SOURCE_INFO #include -#include - -#include #include -#include - -#include #include #include +#include #include -namespace mapbox { -namespace geojsonvt { -class GeoJSONVT; -} // namespace geojsonvt -} // namespace mapbox - namespace mbgl { -class SourceInfo : private util::noncopyable { -public: - ~SourceInfo(); +class TileID; +class SourceInfo { +public: SourceType type = SourceType::Vector; std::string url; std::vector tiles; @@ -36,11 +25,8 @@ public: std::array center = { { 0, 0, 0 } }; std::array bounds = { { -180, -90, 180, 90 } }; std::string source_id = ""; - std::unique_ptr geojsonvt; - void parseTileJSONProperties(const JSValue&); - void parseGeoJSON(const JSValue&); - std::string tileURL(const TileID& id, float pixelRatio) const; + std::string tileURL(const TileID&, float pixelRatio) const; }; } // namespace mbgl diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index fa0dcc1aa..6521d1339 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -112,7 +112,7 @@ bool StyleParser::parseVectorSource(Source& source, const JSValue& sourceVal) { } else { // ...or the TileJSON directly. - source.info.parseTileJSONProperties(sourceVal); + source.parseTileJSON(sourceVal); } return true; @@ -149,7 +149,7 @@ bool StyleParser::parseRasterSource(Source& source, const JSValue& sourceVal) { } else { // ...or the TileJSON directly. - source.info.parseTileJSONProperties(sourceVal); + source.parseTileJSON(sourceVal); } return true; @@ -167,7 +167,7 @@ bool StyleParser::parseGeoJSONSource(Source& source, const JSValue& sourceVal) { source.info.url = { dataVal.GetString(), dataVal.GetStringLength() }; } else if (dataVal.IsObject()) { // We need to parse dataVal as a GeoJSON object - source.info.parseGeoJSON(dataVal); + source.parseGeoJSON(dataVal); } else { Log::Error(Event::ParseStyle, "GeoJSON data must be a URL or an object"); return false;