[core] Use variant<std::string, Tileset> in TileSource
A tile source can either specify a URL to TileJSON, or inline TileJSON.
This commit is contained in:
@@ -107,14 +107,17 @@ OfflineRegionStatus OfflineDownload::getStatus() const {
|
||||
case SourceType::Vector:
|
||||
case SourceType::Raster: {
|
||||
style::TileSource* tileSource = static_cast<style::TileSource*>(source.get());
|
||||
if (tileSource->getTileset()) {
|
||||
result.requiredResourceCount += tileResources(source->type, tileSource->getTileSize(), *tileSource->getTileset()).size();
|
||||
const variant<std::string, Tileset>& urlOrTileset = tileSource->getURLOrTileset();
|
||||
|
||||
if (urlOrTileset.is<Tileset>()) {
|
||||
result.requiredResourceCount += tileResources(source->type, tileSource->getTileSize(), urlOrTileset.get<Tileset>()).size();
|
||||
} else {
|
||||
result.requiredResourceCount += 1;
|
||||
optional<Response> sourceResponse = offlineDatabase.get(Resource::source(tileSource->getURL()));
|
||||
const std::string& url = urlOrTileset.get<std::string>();
|
||||
optional<Response> sourceResponse = offlineDatabase.get(Resource::source(url));
|
||||
if (sourceResponse) {
|
||||
result.requiredResourceCount += tileResources(source->type, tileSource->getTileSize(),
|
||||
*style::parseTileJSON(*sourceResponse->data, tileSource->getURL(), source->type, tileSource->getTileSize())).size();
|
||||
style::TileSource::parseTileJSON(*sourceResponse->data, url, source->type, tileSource->getTileSize())).size();
|
||||
} else {
|
||||
result.requiredResourceCountIsPrecise = false;
|
||||
}
|
||||
@@ -161,16 +164,18 @@ void OfflineDownload::activateDownload() {
|
||||
case SourceType::Vector:
|
||||
case SourceType::Raster: {
|
||||
const style::TileSource* tileSource = static_cast<style::TileSource*>(source.get());
|
||||
const variant<std::string, Tileset>& urlOrTileset = tileSource->getURLOrTileset();
|
||||
const uint16_t tileSize = tileSource->getTileSize();
|
||||
if (tileSource->getTileset()) {
|
||||
ensureTiles(type, tileSize, *tileSource->getTileset());
|
||||
|
||||
if (urlOrTileset.is<Tileset>()) {
|
||||
ensureTiles(type, tileSize, urlOrTileset.get<Tileset>());
|
||||
} else {
|
||||
std::string url = tileSource->getURL();
|
||||
const std::string& url = urlOrTileset.get<std::string>();
|
||||
status.requiredResourceCountIsPrecise = false;
|
||||
requiredSourceURLs.insert(url);
|
||||
|
||||
ensureResource(Resource::source(url), [=] (Response sourceResponse) {
|
||||
ensureTiles(type, tileSize, *style::parseTileJSON(*sourceResponse.data, url, type, tileSize));
|
||||
ensureTiles(type, tileSize, style::TileSource::parseTileJSON(*sourceResponse.data, url, type, tileSize));
|
||||
|
||||
requiredSourceURLs.erase(url);
|
||||
if (requiredSourceURLs.empty()) {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
#include <mbgl/util/mapbox.hpp>
|
||||
#include <mbgl/util/enum.hpp>
|
||||
#include <mbgl/util/tileset.hpp>
|
||||
|
||||
@@ -21,89 +20,11 @@
|
||||
#include <rapidjson/error/en.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
namespace {
|
||||
|
||||
void parseTileJSONMember(const JSValue& value, std::vector<std::string>& 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 parseTileJSONMember(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 parseTileJSONMember(const JSValue& value, uint8_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<uint8_t>::max()) {
|
||||
return;
|
||||
}
|
||||
|
||||
target = uint;
|
||||
}
|
||||
|
||||
void parseTileJSONMember(const JSValue& value, std::array<double, 4>& target, const char* name) {
|
||||
if (!value.HasMember(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const JSValue& property = value[name];
|
||||
if (!property.IsArray() || property.Size() > 4) {
|
||||
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
|
||||
|
||||
Parser::~Parser() = default;
|
||||
|
||||
void Parser::parse(const std::string& json) {
|
||||
@@ -174,44 +95,16 @@ void Parser::parseSources(const JSValue& value) {
|
||||
}
|
||||
|
||||
const std::string id { nameVal.GetString(), nameVal.GetStringLength() };
|
||||
|
||||
std::unique_ptr<Tileset> tileset;
|
||||
std::unique_ptr<Source> source;
|
||||
|
||||
// Sources can have URLs, either because they reference an external TileJSON file, or
|
||||
// because reference a GeoJSON file. They don't have to have one though when all source
|
||||
// parameters are specified inline.
|
||||
std::string url;
|
||||
if (sourceVal.HasMember("url")) {
|
||||
const JSValue& urlVal = sourceVal["url"];
|
||||
if (urlVal.IsString()) {
|
||||
url = { urlVal.GetString(), urlVal.GetStringLength() };
|
||||
} else {
|
||||
Log::Error(Event::ParseStyle, "source url must be a string");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
tileset = parseTileJSON(sourceVal);
|
||||
}
|
||||
|
||||
uint16_t tileSize = util::tileSize;
|
||||
if (sourceVal.HasMember("tileSize")) {
|
||||
const JSValue& tileSizeVal = sourceVal["tileSize"];
|
||||
if (tileSizeVal.IsNumber() && tileSizeVal.GetUint64() <= std::numeric_limits<uint16_t>::max()) {
|
||||
tileSize = tileSizeVal.GetUint64();
|
||||
} else {
|
||||
Log::Error(Event::ParseStyle, "invalid tileSize");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (*type) {
|
||||
case SourceType::Raster:
|
||||
source = std::make_unique<RasterSource>(id, url, tileSize, std::move(tileset));
|
||||
case SourceType::Raster: {
|
||||
source = RasterSource::parse(id, sourceVal);
|
||||
break;
|
||||
}
|
||||
|
||||
case SourceType::Vector:
|
||||
source = std::make_unique<VectorSource>(id, url, std::move(tileset));
|
||||
source = VectorSource::parse(id, sourceVal);
|
||||
break;
|
||||
|
||||
case SourceType::GeoJSON:
|
||||
@@ -230,45 +123,6 @@ void Parser::parseSources(const JSValue& value) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Tileset> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
|
||||
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
|
||||
document.Parse<0>(json.c_str());
|
||||
|
||||
if (document.HasParseError()) {
|
||||
std::stringstream message;
|
||||
message << document.GetErrorOffset() << " - " << rapidjson::GetParseError_En(document.GetParseError());
|
||||
throw std::runtime_error(message.str());
|
||||
}
|
||||
|
||||
std::unique_ptr<Tileset> result = parseTileJSON(document);
|
||||
|
||||
// TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with.
|
||||
if (util::mapbox::isMapboxURL(sourceURL)) {
|
||||
for (auto& url : result->tiles) {
|
||||
url = util::mapbox::canonicalizeTileURL(url, type, tileSize);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Tileset> parseTileJSON(const JSValue& value) {
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
parseTileJSONMember(value, tileset->tiles, "tiles");
|
||||
parseTileJSONMember(value, tileset->zoomRange.min, "minzoom");
|
||||
parseTileJSONMember(value, tileset->zoomRange.max, "maxzoom");
|
||||
parseTileJSONMember(value, tileset->attribution, "attribution");
|
||||
|
||||
std::array<double, 4> array;
|
||||
parseTileJSONMember(value, array, "center");
|
||||
tileset->center = { array[0], array[1] };
|
||||
tileset->zoom = array[2];
|
||||
parseTileJSONMember(value, array, "bounds");
|
||||
tileset->bounds = LatLngBounds::hull({ array[0], array[1] }, { array[2], array[3] });
|
||||
|
||||
return tileset;
|
||||
}
|
||||
|
||||
void Parser::parseLayers(const JSValue& value) {
|
||||
std::vector<std::string> ids;
|
||||
|
||||
|
||||
@@ -14,14 +14,8 @@
|
||||
#include <forward_list>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Tileset;
|
||||
|
||||
namespace style {
|
||||
|
||||
std::unique_ptr<Tileset> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize);
|
||||
std::unique_ptr<Tileset> parseTileJSON(const JSValue&);
|
||||
|
||||
Filter parseFilter(const JSValue&);
|
||||
|
||||
class Parser {
|
||||
|
||||
@@ -1,19 +1,39 @@
|
||||
#include <mbgl/style/sources/raster_source.hpp>
|
||||
#include <mbgl/tile/raster_tile.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
std::unique_ptr<RasterSource> RasterSource::parse(std::string id, const JSValue& value) {
|
||||
optional<variant<std::string, Tileset>> urlOrTileset = TileSource::parseURLOrTileset(value);
|
||||
if (!urlOrTileset) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16_t tileSize = util::tileSize;
|
||||
if (value.HasMember("tileSize")) {
|
||||
const JSValue& tileSizeVal = value["tileSize"];
|
||||
if (tileSizeVal.IsNumber() && tileSizeVal.GetUint64() <= std::numeric_limits<uint16_t>::max()) {
|
||||
tileSize = tileSizeVal.GetUint64();
|
||||
} else {
|
||||
Log::Error(Event::ParseStyle, "invalid tileSize");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<RasterSource>(std::move(id), std::move(*urlOrTileset), tileSize);
|
||||
}
|
||||
|
||||
RasterSource::RasterSource(std::string id_,
|
||||
std::string url_,
|
||||
uint16_t tileSize_,
|
||||
std::unique_ptr<Tileset>&& tileset_)
|
||||
: TileSource(SourceType::Raster, std::move(id_), std::move(url_), tileSize_, std::move(tileset_)) {
|
||||
variant<std::string, Tileset> urlOrTileset_,
|
||||
uint16_t tileSize_)
|
||||
: TileSource(SourceType::Raster, std::move(id_), std::move(urlOrTileset_), tileSize_) {
|
||||
}
|
||||
|
||||
std::unique_ptr<Tile> RasterSource::createTile(const OverscaledTileID& tileID,
|
||||
const UpdateParameters& parameters) {
|
||||
return std::make_unique<RasterTile>(tileID, parameters, *tileset);
|
||||
return std::make_unique<RasterTile>(tileID, parameters, tileset);
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
|
||||
@@ -7,10 +7,9 @@ namespace style {
|
||||
|
||||
class RasterSource : public TileSource {
|
||||
public:
|
||||
RasterSource(std::string id,
|
||||
std::string url,
|
||||
uint16_t tileSize,
|
||||
std::unique_ptr<Tileset>&&);
|
||||
static std::unique_ptr<RasterSource> parse(std::string id, const JSValue&);
|
||||
|
||||
RasterSource(std::string id, variant<std::string, Tileset>, uint16_t tileSize);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
|
||||
|
||||
@@ -4,15 +4,21 @@
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
VectorSource::VectorSource(std::string id_,
|
||||
std::string url_,
|
||||
std::unique_ptr<Tileset>&& tileset_)
|
||||
: TileSource(SourceType::Vector, std::move(id_), std::move(url_), util::tileSize, std::move(tileset_)) {
|
||||
std::unique_ptr<VectorSource> VectorSource::parse(std::string id, const JSValue& value) {
|
||||
optional<variant<std::string, Tileset>> urlOrTileset = TileSource::parseURLOrTileset(value);
|
||||
if (!urlOrTileset) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<VectorSource>(std::move(id), std::move(*urlOrTileset));
|
||||
}
|
||||
|
||||
VectorSource::VectorSource(std::string id_, variant<std::string, Tileset> urlOrTileset_)
|
||||
: TileSource(SourceType::Vector, std::move(id_), std::move(urlOrTileset_), util::tileSize) {
|
||||
}
|
||||
|
||||
std::unique_ptr<Tile> VectorSource::createTile(const OverscaledTileID& tileID,
|
||||
const UpdateParameters& parameters) {
|
||||
return std::make_unique<VectorTile>(tileID, id, parameters, *tileset);
|
||||
return std::make_unique<VectorTile>(tileID, id, parameters, tileset);
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace style {
|
||||
|
||||
class VectorSource : public TileSource {
|
||||
public:
|
||||
VectorSource(std::string id,
|
||||
std::string url,
|
||||
std::unique_ptr<Tileset>&&);
|
||||
static std::unique_ptr<VectorSource> parse(std::string id, const JSValue&);
|
||||
|
||||
VectorSource(std::string id, variant<std::string, Tileset>);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
|
||||
|
||||
@@ -2,31 +2,163 @@
|
||||
#include <mbgl/style/source_observer.hpp>
|
||||
#include <mbgl/style/parser.hpp>
|
||||
#include <mbgl/util/tileset.hpp>
|
||||
#include <mbgl/util/mapbox.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/error/en.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
namespace {
|
||||
|
||||
void parseTileJSONMember(const JSValue& value, std::vector<std::string>& 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 parseTileJSONMember(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 parseTileJSONMember(const JSValue& value, uint8_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<uint8_t>::max()) {
|
||||
return;
|
||||
}
|
||||
|
||||
target = uint;
|
||||
}
|
||||
|
||||
void parseTileJSONMember(const JSValue& value, std::array<double, 4>& target, const char* name) {
|
||||
if (!value.HasMember(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const JSValue& property = value[name];
|
||||
if (!property.IsArray() || property.Size() > 4) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Tileset parseTileJSON(const JSValue& value) {
|
||||
Tileset result;
|
||||
|
||||
parseTileJSONMember(value, result.tiles, "tiles");
|
||||
parseTileJSONMember(value, result.zoomRange.min, "minzoom");
|
||||
parseTileJSONMember(value, result.zoomRange.max, "maxzoom");
|
||||
parseTileJSONMember(value, result.attribution, "attribution");
|
||||
|
||||
std::array<double, 4> array;
|
||||
parseTileJSONMember(value, array, "center");
|
||||
result.center = { array[0], array[1] };
|
||||
result.zoom = array[2];
|
||||
parseTileJSONMember(value, array, "bounds");
|
||||
result.bounds = LatLngBounds::hull({ array[0], array[1] }, { array[2], array[3] });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
Tileset TileSource::parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
|
||||
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
|
||||
document.Parse<0>(json.c_str());
|
||||
|
||||
if (document.HasParseError()) {
|
||||
std::stringstream message;
|
||||
message << document.GetErrorOffset() << " - " << rapidjson::GetParseError_En(document.GetParseError());
|
||||
throw std::runtime_error(message.str());
|
||||
}
|
||||
|
||||
Tileset result = mbgl::style::parseTileJSON(document);
|
||||
|
||||
// TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with.
|
||||
if (util::mapbox::isMapboxURL(sourceURL)) {
|
||||
for (auto& url : result.tiles) {
|
||||
url = util::mapbox::canonicalizeTileURL(url, type, tileSize);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
optional<variant<std::string, Tileset>> TileSource::parseURLOrTileset(const JSValue& value) {
|
||||
if (!value.HasMember("url")) {
|
||||
return { mbgl::style::parseTileJSON(value) };
|
||||
}
|
||||
|
||||
const JSValue& urlVal = value["url"];
|
||||
if (!urlVal.IsString()) {
|
||||
Log::Error(Event::ParseStyle, "source url must be a string");
|
||||
return {};
|
||||
}
|
||||
|
||||
return { std::string(urlVal.GetString(), urlVal.GetStringLength()) };
|
||||
}
|
||||
|
||||
TileSource::TileSource(SourceType type_,
|
||||
std::string id_,
|
||||
std::string url_,
|
||||
uint16_t tileSize_,
|
||||
std::unique_ptr<Tileset>&& tileset_)
|
||||
variant<std::string, Tileset> urlOrTileset_,
|
||||
uint16_t tileSize_)
|
||||
: Source(type_, std::move(id_)),
|
||||
tileSize(tileSize_),
|
||||
url(std::move(url_)),
|
||||
tileset(std::move(tileset_)) {
|
||||
urlOrTileset(std::move(urlOrTileset_)),
|
||||
tileSize(tileSize_) {
|
||||
}
|
||||
|
||||
TileSource::~TileSource() = default;
|
||||
|
||||
Range<uint8_t> TileSource::getZoomRange() {
|
||||
return tileset->zoomRange;
|
||||
}
|
||||
|
||||
void TileSource::load(FileSource& fileSource) {
|
||||
if (url.empty()) {
|
||||
// If the URL is empty, the TileJSON was specified inline in the stylesheet.
|
||||
if (urlOrTileset.is<Tileset>()) {
|
||||
tileset = urlOrTileset.get<Tileset>();
|
||||
loaded = true;
|
||||
return;
|
||||
}
|
||||
@@ -35,8 +167,8 @@ void TileSource::load(FileSource& fileSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
// URL may either be a TileJSON file, or a GeoJSON file.
|
||||
req = fileSource.request(Resource::source(url), [this](Response res) {
|
||||
const std::string& url = urlOrTileset.get<std::string>();
|
||||
req = fileSource.request(Resource::source(url), [this, url](Response res) {
|
||||
if (res.error) {
|
||||
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
|
||||
} else if (res.notModified) {
|
||||
@@ -44,20 +176,20 @@ void TileSource::load(FileSource& fileSource) {
|
||||
} else if (res.noContent) {
|
||||
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
|
||||
} else {
|
||||
std::unique_ptr<Tileset> newTileset;
|
||||
Tileset newTileset;
|
||||
|
||||
// Create a new copy of the Tileset object that holds the base values we've parsed
|
||||
// from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved
|
||||
// via the URL.
|
||||
try {
|
||||
newTileset = style::parseTileJSON(*res.data, url, type, tileSize);
|
||||
newTileset = parseTileJSON(*res.data, url, type, tileSize);
|
||||
} catch (...) {
|
||||
observer->onSourceError(*this, std::current_exception());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether previous information specifies different tile
|
||||
if (tileset && tileset->tiles != newTileset->tiles) {
|
||||
if (tileset.tiles != newTileset.tiles) {
|
||||
// Tile URLs changed: force tiles to be reloaded.
|
||||
invalidateTiles();
|
||||
|
||||
@@ -76,12 +208,18 @@ void TileSource::load(FileSource& fileSource) {
|
||||
// Center/bounds changed: We're not using these values currently
|
||||
}
|
||||
|
||||
tileset = std::move(newTileset);
|
||||
tileset = newTileset;
|
||||
loaded = true;
|
||||
|
||||
observer->onSourceLoaded(*this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Range<uint8_t> TileSource::getZoomRange() {
|
||||
assert(loaded);
|
||||
return tileset.zoomRange;
|
||||
}
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/source.hpp>
|
||||
#include <mbgl/util/tileset.hpp>
|
||||
#include <mbgl/util/variant.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/util/rapidjson.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Tileset;
|
||||
class AsyncRequest;
|
||||
|
||||
namespace style {
|
||||
@@ -15,25 +18,33 @@ namespace style {
|
||||
*/
|
||||
class TileSource : public Source {
|
||||
public:
|
||||
// A tile source can either specify a URL to TileJSON, or inline TileJSON.
|
||||
static optional<variant<std::string, Tileset>> parseURLOrTileset(const JSValue&);
|
||||
static Tileset parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize);
|
||||
|
||||
TileSource(SourceType,
|
||||
std::string id,
|
||||
std::string url,
|
||||
uint16_t tileSize,
|
||||
std::unique_ptr<Tileset>&&);
|
||||
variant<std::string, Tileset> urlOrTileset,
|
||||
uint16_t tileSize);
|
||||
~TileSource() override;
|
||||
|
||||
void load(FileSource&) final;
|
||||
|
||||
const std::string& getURL() const { return url; }
|
||||
uint16_t getTileSize() const final { return tileSize; }
|
||||
const Tileset* getTileset() const { return tileset.get(); }
|
||||
uint16_t getTileSize() const final {
|
||||
return tileSize;
|
||||
}
|
||||
|
||||
const variant<std::string, Tileset>& getURLOrTileset() const {
|
||||
return urlOrTileset;
|
||||
}
|
||||
|
||||
protected:
|
||||
Range<uint8_t> getZoomRange() final;
|
||||
|
||||
const variant<std::string, Tileset> urlOrTileset;
|
||||
const uint16_t tileSize;
|
||||
const std::string url;
|
||||
std::unique_ptr<const Tileset> tileset;
|
||||
|
||||
Tileset tileset;
|
||||
std::unique_ptr<AsyncRequest> req;
|
||||
};
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ TEST(Source, LoadingFail) {
|
||||
test.end();
|
||||
};
|
||||
|
||||
VectorSource source("source", "url", nullptr);
|
||||
VectorSource source("source", "url");
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
|
||||
@@ -110,7 +110,7 @@ TEST(Source, LoadingCorrupt) {
|
||||
test.end();
|
||||
};
|
||||
|
||||
VectorSource source("source", "url", nullptr);
|
||||
VectorSource source("source", "url");
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
|
||||
@@ -135,10 +135,10 @@ TEST(Source, RasterTileEmpty) {
|
||||
FAIL() << "Should never be called";
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
RasterSource source("source", "", 512, std::move(tileset));
|
||||
RasterSource source("source", tileset, 512);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -164,10 +164,10 @@ TEST(Source, VectorTileEmpty) {
|
||||
FAIL() << "Should never be called";
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
VectorSource source("source", "", std::move(tileset));
|
||||
VectorSource source("source", tileset);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -193,10 +193,10 @@ TEST(Source, RasterTileFail) {
|
||||
test.end();
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
RasterSource source("source", "", 512, std::move(tileset));
|
||||
RasterSource source("source", tileset, 512);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -222,10 +222,10 @@ TEST(Source, VectorTileFail) {
|
||||
test.end();
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
VectorSource source("source", "", std::move(tileset));
|
||||
VectorSource source("source", tileset);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -250,10 +250,10 @@ TEST(Source, RasterTileCorrupt) {
|
||||
test.end();
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
RasterSource source("source", "", 512, std::move(tileset));
|
||||
RasterSource source("source", tileset, 512);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -282,10 +282,10 @@ TEST(Source, VectorTileCorrupt) {
|
||||
layer->setSource("source", "water");
|
||||
test.style.addLayer(std::move(layer));
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
VectorSource source("source", "", std::move(tileset));
|
||||
VectorSource source("source", tileset);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -309,10 +309,10 @@ TEST(Source, RasterTileCancel) {
|
||||
FAIL() << "Should never be called";
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
RasterSource source("source", "", 512, std::move(tileset));
|
||||
RasterSource source("source", tileset, 512);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
@@ -336,10 +336,10 @@ TEST(Source, VectorTileCancel) {
|
||||
FAIL() << "Should never be called";
|
||||
};
|
||||
|
||||
auto tileset = std::make_unique<Tileset>();
|
||||
tileset->tiles = { "tiles" };
|
||||
Tileset tileset;
|
||||
tileset.tiles = { "tiles" };
|
||||
|
||||
VectorSource source("source", "", std::move(tileset));
|
||||
VectorSource source("source", tileset);
|
||||
source.setObserver(&test.observer);
|
||||
source.load(test.fileSource);
|
||||
source.update(test.updateParameters);
|
||||
|
||||
@@ -87,36 +87,6 @@ INSTANTIATE_TEST_CASE_P(StyleParser, StyleParserTest, ::testing::ValuesIn([] {
|
||||
return names;
|
||||
}()));
|
||||
|
||||
TEST(StyleParser, ParseTileJSONRaster) {
|
||||
auto result = style::parseTileJSON(
|
||||
util::read_file("test/fixtures/style_parser/tilejson.raster.json"),
|
||||
"mapbox://mapbox.satellite",
|
||||
SourceType::Raster,
|
||||
256);
|
||||
|
||||
EXPECT_EQ(0, result->zoomRange.min);
|
||||
EXPECT_EQ(15, result->zoomRange.max);
|
||||
EXPECT_EQ("attribution", result->attribution);
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
EXPECT_EQ("mapbox://tiles/mapbox.satellite/{z}/{x}/{y}{ratio}.webp", result->tiles[0]);
|
||||
#else
|
||||
EXPECT_EQ("mapbox://tiles/mapbox.satellite/{z}/{x}/{y}{ratio}.png", result->tiles[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(StyleParser, ParseTileJSONVector) {
|
||||
auto result = style::parseTileJSON(
|
||||
util::read_file("test/fixtures/style_parser/tilejson.vector.json"),
|
||||
"mapbox://mapbox.streets",
|
||||
SourceType::Vector,
|
||||
256);
|
||||
|
||||
EXPECT_EQ(0, result->zoomRange.min);
|
||||
EXPECT_EQ(15, result->zoomRange.max);
|
||||
EXPECT_EQ("attribution", result->attribution);
|
||||
EXPECT_EQ("mapbox://tiles/mapbox.streets/{z}/{x}/{y}.vector.pbf", result->tiles[0]);
|
||||
}
|
||||
|
||||
TEST(StyleParser, FontStacks) {
|
||||
style::Parser parser;
|
||||
parser.parse(util::read_file("test/fixtures/style_parser/font_stacks.json"));
|
||||
|
||||
37
test/style/tile_source.cpp
Normal file
37
test/style/tile_source.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/style/tile_source.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
using namespace mbgl::style;
|
||||
|
||||
TEST(TileSource, ParseTileJSONRaster) {
|
||||
auto result = TileSource::parseTileJSON(
|
||||
util::read_file("test/fixtures/style_parser/tilejson.raster.json"),
|
||||
"mapbox://mapbox.satellite",
|
||||
SourceType::Raster,
|
||||
256);
|
||||
|
||||
EXPECT_EQ(0, result.zoomRange.min);
|
||||
EXPECT_EQ(15, result.zoomRange.max);
|
||||
EXPECT_EQ("attribution", result.attribution);
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
EXPECT_EQ("mapbox://tiles/mapbox.satellite/{z}/{x}/{y}{ratio}.webp", result.tiles[0]);
|
||||
#else
|
||||
EXPECT_EQ("mapbox://tiles/mapbox.satellite/{z}/{x}/{y}{ratio}.png", result.tiles[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(TileSource, ParseTileJSONVector) {
|
||||
auto result = TileSource::parseTileJSON(
|
||||
util::read_file("test/fixtures/style_parser/tilejson.vector.json"),
|
||||
"mapbox://mapbox.streets",
|
||||
SourceType::Vector,
|
||||
256);
|
||||
|
||||
EXPECT_EQ(0, result.zoomRange.min);
|
||||
EXPECT_EQ(15, result.zoomRange.max);
|
||||
EXPECT_EQ("attribution", result.attribution);
|
||||
EXPECT_EQ("mapbox://tiles/mapbox.streets/{z}/{x}/{y}.vector.pbf", result.tiles[0]);
|
||||
}
|
||||
@@ -73,6 +73,7 @@
|
||||
'style/source.cpp',
|
||||
'style/style.cpp',
|
||||
'style/style_layer.cpp',
|
||||
'style/tile_source.cpp',
|
||||
'style/filter.cpp',
|
||||
'style/functions.cpp',
|
||||
'style/style_parser.cpp',
|
||||
|
||||
Reference in New Issue
Block a user