#include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace conversion { // A tile source can either specify a URL to TileJSON, or inline TileJSON. static optional> convertURLOrTileset(const Convertible& value, Error& error) { auto urlVal = objectMember(value, "url"); if (!urlVal) { optional tileset = convert(value, error); if (!tileset) { return {}; } return { *tileset }; } optional url = toString(*urlVal); if (!url) { error = { "source url must be a string" }; return {}; } return { *url }; } static optional> convertRasterSource(const std::string& id, const Convertible& value, Error& error) { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return {}; } uint16_t tileSize = util::tileSize; auto tileSizeValue = objectMember(value, "tileSize"); if (tileSizeValue) { optional size = toNumber(*tileSizeValue); if (!size || *size < 0 || *size > std::numeric_limits::max()) { error = { "invalid tileSize" }; return {}; } tileSize = *size; } return { std::make_unique(id, std::move(*urlOrTileset), tileSize) }; } static optional> convertRasterDEMSource(const std::string& id, const Convertible& value, Error& error) { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return {}; } uint16_t tileSize = util::tileSize; auto tileSizeValue = objectMember(value, "tileSize"); if (tileSizeValue) { optional size = toNumber(*tileSizeValue); if (!size || *size < 0 || *size > std::numeric_limits::max()) { error = { "invalid tileSize" }; return {}; } tileSize = *size; } return { std::make_unique(id, std::move(*urlOrTileset), tileSize) }; } static optional> convertVectorSource(const std::string& id, const Convertible& value, Error& error) { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return {}; } return { std::make_unique(id, std::move(*urlOrTileset)) }; } static optional> convertGeoJSONSource(const std::string& id, const Convertible& value, Error& error) { auto dataValue = objectMember(value, "data"); if (!dataValue) { error = { "GeoJSON source must have a data value" }; return {}; } optional options = convert(value, error); if (!options) { return {}; } auto result = std::make_unique(id, *options); if (isObject(*dataValue)) { optional geoJSON = convert(*dataValue, error); if (!geoJSON) { return {}; } result->setGeoJSON(std::move(*geoJSON)); } else if (toString(*dataValue)) { result->setURL(*toString(*dataValue)); } else { error = { "GeoJSON data must be a URL or an object" }; return {}; } return { std::move(result) }; } static optional> convertImageSource(const std::string& id, const Convertible& value, Error& error) { auto urlValue = objectMember(value, "url"); if (!urlValue) { error = { "Image source must have a url value" }; return {}; } auto urlString = toString(*urlValue); if (!urlString) { error = { "Image url must be a URL string" }; return {}; } auto coordinatesValue = objectMember(value, "coordinates"); if (!coordinatesValue) { error = { "Image source must have a coordinates values" }; return {}; } if (!isArray(*coordinatesValue) || arrayLength(*coordinatesValue) != 4) { error = { "Image coordinates must be an array of four longitude latitude pairs" }; return {}; } std::array coordinates; for (std::size_t i=0; i < 4; i++) { auto latLng = conversion::convert(arrayMember(*coordinatesValue,i), error); if (!latLng) { return {}; } coordinates[i] = *latLng; } auto result = std::make_unique(id, coordinates); result->setURL(*urlString); return { std::move(result) }; } optional> Converter>::operator()(const Convertible& value, Error& error, const std::string& id) const { if (!isObject(value)) { error = { "source must be an object" }; return {}; } auto typeValue = objectMember(value, "type"); if (!typeValue) { error = { "source must have a type" }; return {}; } optional type = toString(*typeValue); if (!type) { error = { "source type must be a string" }; return {}; } const std::string tname = *type; if (*type == "raster") { return convertRasterSource(id, value, error); } else if (*type == "raster-dem") { return convertRasterDEMSource(id, value, error); } else if (*type == "vector") { return convertVectorSource(id, value, error); } else if (*type == "geojson") { return convertGeoJSONSource(id, value, error); } else if (*type == "image") { return convertImageSource(id, value, error); } else { error = { "invalid source type" }; return {}; } } } // namespace conversion } // namespace style } // namespace mbgl