Fix for raster dem encoding override in style.json (#3570)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Scott Hoyt
2025-08-01 04:50:09 -07:00
committed by GitHub
parent 7d46c00529
commit ca5f79c12d
28 changed files with 347 additions and 285 deletions

View File

@@ -311,6 +311,7 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/light.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/position.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/property_value.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/raster_dem_options.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/rotation.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/tileset.hpp
@@ -378,6 +379,7 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/geojson_source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/image_source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/raster_dem_source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/tile_source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/raster_source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/vector_source.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/style/sprite.hpp
@@ -690,6 +692,7 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/light.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/position.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/property_value.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/raster_dem_options.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/rotation.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/source.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/stringify.hpp
@@ -815,12 +818,11 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/image_source_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/image_source_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_dem_source.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/tile_source.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_source.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_source_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_source_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/tile_source_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/tile_source_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/vector_source.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/vector_source_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/vector_source_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/style.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/style_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/style/style_impl.hpp

View File

@@ -345,6 +345,7 @@ MLN_CORE_SOURCE = [
"src/mbgl/style/conversion/light.cpp",
"src/mbgl/style/conversion/position.cpp",
"src/mbgl/style/conversion/property_value.cpp",
"src/mbgl/style/conversion/raster_dem_options.cpp",
"src/mbgl/style/conversion/rotation.cpp",
"src/mbgl/style/conversion/source.cpp",
"src/mbgl/style/conversion/stringify.hpp",
@@ -450,12 +451,11 @@ MLN_CORE_SOURCE = [
"src/mbgl/style/sources/image_source_impl.cpp",
"src/mbgl/style/sources/image_source_impl.hpp",
"src/mbgl/style/sources/raster_dem_source.cpp",
"src/mbgl/style/sources/tile_source.cpp",
"src/mbgl/style/sources/raster_source.cpp",
"src/mbgl/style/sources/raster_source_impl.cpp",
"src/mbgl/style/sources/raster_source_impl.hpp",
"src/mbgl/style/sources/tile_source_impl.cpp",
"src/mbgl/style/sources/tile_source_impl.hpp",
"src/mbgl/style/sources/vector_source.cpp",
"src/mbgl/style/sources/vector_source_impl.cpp",
"src/mbgl/style/sources/vector_source_impl.hpp",
"src/mbgl/style/style.cpp",
"src/mbgl/style/style_impl.cpp",
"src/mbgl/style/style_impl.hpp",
@@ -696,6 +696,7 @@ MLN_CORE_HEADERS = [
"include/mbgl/style/conversion/light.hpp",
"include/mbgl/style/conversion/position.hpp",
"include/mbgl/style/conversion/property_value.hpp",
"include/mbgl/style/conversion/raster_dem_options.hpp",
"include/mbgl/style/conversion/rotation.hpp",
"include/mbgl/style/conversion/source.hpp",
"include/mbgl/style/conversion/tileset.hpp",
@@ -755,6 +756,7 @@ MLN_CORE_HEADERS = [
"include/mbgl/style/sources/geojson_source.hpp",
"include/mbgl/style/sources/image_source.hpp",
"include/mbgl/style/sources/raster_dem_source.hpp",
"include/mbgl/style/sources/tile_source.hpp",
"include/mbgl/style/sources/raster_source.hpp",
"include/mbgl/style/sources/vector_source.hpp",
"include/mbgl/style/sprite.hpp",

View File

@@ -0,0 +1,17 @@
#pragma once
#include <mbgl/style/sources/raster_dem_source.hpp>
#include <mbgl/style/conversion.hpp>
namespace mbgl {
namespace style {
namespace conversion {
template <>
struct Converter<RasterDEMOptions> {
std::optional<RasterDEMOptions> operator()(const Convertible& value, Error& error) const;
};
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -6,14 +6,25 @@
namespace mbgl {
class AsyncRequest;
namespace style {
struct RasterDEMOptions {
std::optional<Tileset::DEMEncoding> encoding = std::nullopt;
};
class RasterDEMSource : public RasterSource {
public:
RasterDEMSource(std::string id, variant<std::string, Tileset> urlOrTileset, uint16_t tileSize);
RasterDEMSource(std::string id,
variant<std::string, Tileset> urlOrTileset,
uint16_t tileSize,
std::optional<RasterDEMOptions> options = std::nullopt);
bool supportsLayerType(const mbgl::style::LayerTypeInfo*) const override;
protected:
void setTilesetOverrides(Tileset& tileset) override;
private:
std::optional<RasterDEMOptions> options;
};
template <>

View File

@@ -1,45 +1,21 @@
#pragma once
#include <mbgl/style/source.hpp>
#include <mbgl/style/sources/tile_source.hpp>
#include <mbgl/util/tileset.hpp>
#include <mbgl/util/variant.hpp>
namespace mbgl {
class AsyncRequest;
namespace style {
class RasterSource : public Source {
class RasterSource : public TileSource {
public:
RasterSource(std::string id,
variant<std::string, Tileset> urlOrTileset,
uint16_t tileSize,
SourceType sourceType = SourceType::Raster);
~RasterSource() override;
const variant<std::string, Tileset>& getURLOrTileset() const;
std::optional<std::string> getURL() const;
uint16_t getTileSize() const;
class Impl;
const Impl& impl() const;
void loadDescription(FileSource&) final;
bool supportsLayerType(const mbgl::style::LayerTypeInfo*) const override;
mapbox::base::WeakPtr<Source> makeWeakPtr() final { return weakFactory.makeWeakPtr(); }
protected:
Mutable<Source::Impl> createMutable() const noexcept final;
private:
const variant<std::string, Tileset> urlOrTileset;
std::unique_ptr<AsyncRequest> req;
mapbox::base::WeakPtrFactory<Source> weakFactory{this};
// Do not add members here, see `WeakPtrFactory`
};
template <>

View File

@@ -0,0 +1,47 @@
#pragma once
#include <mbgl/style/source.hpp>
#include <mbgl/util/tileset.hpp>
#include <mbgl/util/variant.hpp>
namespace mbgl {
class AsyncRequest;
namespace style {
class TileSource : public Source {
public:
TileSource(std::string id, variant<std::string, Tileset> urlOrTileset, uint16_t tileSize, SourceType sourceType);
~TileSource() override;
const variant<std::string, Tileset>& getURLOrTileset() const;
std::optional<std::string> getURL() const;
uint16_t getTileSize() const;
class Impl;
const Impl& impl() const;
void loadDescription(FileSource&) final;
mapbox::base::WeakPtr<Source> makeWeakPtr() final { return weakFactory.makeWeakPtr(); }
protected:
Mutable<Source::Impl> createMutable() const noexcept final;
virtual void setTilesetOverrides(Tileset& tileset);
private:
const variant<std::string, Tileset> urlOrTileset;
std::unique_ptr<AsyncRequest> req;
mapbox::base::WeakPtrFactory<Source> weakFactory{this};
// Do not add members here, see `WeakPtrFactory`
};
template <>
inline bool Source::is<TileSource>() const {
return getType() == SourceType::Raster;
}
} // namespace style
} // namespace mbgl

View File

@@ -1,6 +1,6 @@
#pragma once
#include <mbgl/style/source.hpp>
#include <mbgl/style/sources/tile_source.hpp>
#include <mbgl/util/tileset.hpp>
#include <mbgl/util/variant.hpp>
@@ -10,21 +10,14 @@ class AsyncRequest;
namespace style {
class VectorSource final : public Source {
class VectorSource final : public TileSource {
public:
VectorSource(std::string id,
variant<std::string, Tileset> urlOrTileset,
std::optional<float> maxZoom = std::nullopt,
std::optional<float> minZoom = std::nullopt);
~VectorSource() final;
const variant<std::string, Tileset>& getURLOrTileset() const;
std::optional<std::string> getURL() const;
class Impl;
const Impl& impl() const;
void loadDescription(FileSource&) final;
void setTilesetOverrides(Tileset& tileset) override;
/// @brief Gets the tile urls for this vector source.
/// @return List of tile urls.
@@ -36,18 +29,9 @@ public:
bool supportsLayerType(const mbgl::style::LayerTypeInfo*) const override;
mapbox::base::WeakPtr<Source> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }
protected:
Mutable<Source::Impl> createMutable() const noexcept final;
private:
const variant<std::string, Tileset> urlOrTileset;
std::unique_ptr<AsyncRequest> req;
std::optional<float> maxZoom;
std::optional<float> minZoom;
mapbox::base::WeakPtrFactory<Source> weakFactory{this};
// Do not add members here, see `WeakPtrFactory`
};
template <>

View File

@@ -24,13 +24,13 @@ std::unique_ptr<RenderSource> RenderSource::create(const Immutable<Source::Impl>
const TaggedScheduler& threadPool_) {
switch (impl->type) {
case SourceType::Vector:
return std::make_unique<RenderVectorSource>(staticImmutableCast<VectorSource::Impl>(impl),
return std::make_unique<RenderVectorSource>(staticImmutableCast<TileSource::Impl>(impl),
std::move(threadPool_));
case SourceType::Raster:
return std::make_unique<RenderRasterSource>(staticImmutableCast<RasterSource::Impl>(impl),
return std::make_unique<RenderRasterSource>(staticImmutableCast<TileSource::Impl>(impl),
std::move(threadPool_));
case SourceType::RasterDEM:
return std::make_unique<RenderRasterDEMSource>(staticImmutableCast<RasterSource::Impl>(impl),
return std::make_unique<RenderRasterDEMSource>(staticImmutableCast<TileSource::Impl>(impl),
std::move(threadPool_));
case SourceType::GeoJSON:
return std::make_unique<RenderGeoJSONSource>(staticImmutableCast<GeoJSONSource::Impl>(impl),

View File

@@ -10,12 +10,12 @@ namespace mbgl {
using namespace style;
RenderRasterDEMSource::RenderRasterDEMSource(Immutable<style::RasterSource::Impl> impl_,
RenderRasterDEMSource::RenderRasterDEMSource(Immutable<style::TileSource::Impl> impl_,
const TaggedScheduler& threadPool_)
: RenderTileSetSource(std::move(impl_), threadPool_) {}
const style::RasterSource::Impl& RenderRasterDEMSource::impl() const {
return static_cast<const style::RasterSource::Impl&>(*baseImpl);
const style::TileSource::Impl& RenderRasterDEMSource::impl() const {
return static_cast<const style::TileSource::Impl&>(*baseImpl);
}
const std::optional<Tileset>& RenderRasterDEMSource::getTileset() const {

View File

@@ -1,13 +1,13 @@
#pragma once
#include <mbgl/renderer/sources/render_tile_source.hpp>
#include <mbgl/style/sources/raster_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
namespace mbgl {
class RenderRasterDEMSource final : public RenderTileSetSource {
public:
explicit RenderRasterDEMSource(Immutable<style::RasterSource::Impl>, const TaggedScheduler&);
explicit RenderRasterDEMSource(Immutable<style::TileSource::Impl>, const TaggedScheduler&);
std::unordered_map<std::string, std::vector<Feature>> queryRenderedFeatures(
const ScreenLineString& geometry,
@@ -27,7 +27,7 @@ private:
const TileParameters&) override;
const std::optional<Tileset>& getTileset() const override;
const style::RasterSource::Impl& impl() const;
const style::TileSource::Impl& impl() const;
void onTileChanged(Tile&) override;
};

View File

@@ -8,11 +8,11 @@ namespace mbgl {
using namespace style;
RenderRasterSource::RenderRasterSource(Immutable<style::RasterSource::Impl> impl_, const TaggedScheduler& threadPool_)
RenderRasterSource::RenderRasterSource(Immutable<style::TileSource::Impl> impl_, const TaggedScheduler& threadPool_)
: RenderTileSetSource(std::move(impl_), threadPool_) {}
inline const style::RasterSource::Impl& RenderRasterSource::impl() const {
return static_cast<const style::RasterSource::Impl&>(*baseImpl);
inline const style::TileSource::Impl& RenderRasterSource::impl() const {
return static_cast<const style::TileSource::Impl&>(*baseImpl);
}
const std::optional<Tileset>& RenderRasterSource::getTileset() const {

View File

@@ -1,13 +1,13 @@
#pragma once
#include <mbgl/renderer/sources/render_tile_source.hpp>
#include <mbgl/style/sources/raster_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
namespace mbgl {
class RenderRasterSource final : public RenderTileSetSource {
public:
explicit RenderRasterSource(Immutable<style::RasterSource::Impl>, const TaggedScheduler&);
explicit RenderRasterSource(Immutable<style::TileSource::Impl>, const TaggedScheduler&);
private:
void prepare(const SourcePrepareParameters&) final;
@@ -29,7 +29,7 @@ private:
const TileParameters&) override;
const std::optional<Tileset>& getTileset() const override;
const style::RasterSource::Impl& impl() const;
const style::TileSource::Impl& impl() const;
};
} // namespace mbgl

View File

@@ -3,7 +3,7 @@
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/source_state.hpp>
#include <mbgl/renderer/tile_pyramid.hpp>
#include <mbgl/style/sources/vector_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/gfx/context.hpp>

View File

@@ -8,11 +8,11 @@ namespace mbgl {
using namespace style;
RenderVectorSource::RenderVectorSource(Immutable<style::VectorSource::Impl> impl_, const TaggedScheduler& threadPool_)
RenderVectorSource::RenderVectorSource(Immutable<style::TileSource::Impl> impl_, const TaggedScheduler& threadPool_)
: RenderTileSetSource(std::move(impl_), threadPool_) {}
const std::optional<Tileset>& RenderVectorSource::getTileset() const {
return static_cast<const style::VectorSource::Impl&>(*baseImpl).tileset;
return static_cast<const style::TileSource::Impl&>(*baseImpl).tileset;
}
void RenderVectorSource::updateInternal(const Tileset& tileset,

View File

@@ -2,13 +2,13 @@
#include <mbgl/renderer/sources/render_tile_source.hpp>
#include <mbgl/renderer/tile_pyramid.hpp>
#include <mbgl/style/sources/vector_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
namespace mbgl {
class RenderVectorSource final : public RenderTileSetSource {
public:
explicit RenderVectorSource(Immutable<style::VectorSource::Impl>, const TaggedScheduler&);
explicit RenderVectorSource(Immutable<style::TileSource::Impl>, const TaggedScheduler&);
private:
void updateInternal(const Tileset&,

View File

@@ -0,0 +1,34 @@
#include <mbgl/style/conversion/raster_dem_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <sstream>
namespace mbgl {
namespace style {
namespace conversion {
std::optional<RasterDEMOptions> Converter<RasterDEMOptions>::operator()(const Convertible& value, Error& error) const {
RasterDEMOptions options;
auto encodingValue = objectMember(value, "encoding");
if (encodingValue) {
std::optional<std::string> encoding = toString(*encodingValue);
if (encoding && *encoding == "terrarium") {
options.encoding = {Tileset::DEMEncoding::Terrarium};
} else if (encoding && *encoding == "mapbox") {
options.encoding = {Tileset::DEMEncoding::Mapbox};
} else {
error.message =
"invalid raster-dem encoding type - valid types are 'mapbox' "
"and 'terrarium'";
return std::nullopt;
}
}
return {std::move(options)};
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/conversion/coordinate.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/geojson_options.hpp>
#include <mbgl/style/conversion/raster_dem_options.hpp>
#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
@@ -76,7 +77,14 @@ static std::optional<std::unique_ptr<Source>> convertRasterDEMSource(const std::
tileSize = static_cast<uint16_t>(*size);
}
return {std::make_unique<RasterDEMSource>(id, std::move(*urlOrTileset), tileSize)};
/*
TODO: Refactor TileJSON parsing responsibilities. Currently `Tileset` handles full TileJSON parsing with optional
parameters. Since style.json can contain TileJSON parameter overrides or non-TileJSON spec parameters, a
separate mechanism is needed. Ideally these two pathways share parsing logic.
*/
std::optional<RasterDEMOptions> options = convert<RasterDEMOptions>(value, error);
return {std::make_unique<RasterDEMSource>(id, std::move(*urlOrTileset), tileSize, options)};
}
static std::optional<std::unique_ptr<Source>> convertVectorSource(const std::string& id,

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/conversion/raster_dem_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/math/clamp.hpp>
@@ -38,15 +39,10 @@ std::optional<Tileset> Converter<Tileset>::operator()(const Convertible& value,
}
}
auto encodingValue = objectMember(value, "encoding");
if (encodingValue) {
std::optional<std::string> encoding = toString(*encodingValue);
if (encoding && *encoding == "terrarium") {
result.encoding = Tileset::DEMEncoding::Terrarium;
} else if (encoding && *encoding != "mapbox") {
error.message =
"invalid raster-dem encoding type - valid types are 'mapbox' "
"and 'terrarium' ";
auto rasterDEMOptions = convert<RasterDEMOptions>(value, error);
if (rasterDEMOptions) {
if (std::optional<Tileset::DEMEncoding> encoding = rasterDEMOptions.value().encoding) {
result.encoding = encoding.value();
}
}

View File

@@ -3,7 +3,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source_observer.hpp>
#include <mbgl/style/sources/raster_dem_source.hpp>
#include <mbgl/style/sources/raster_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/mapbox.hpp>
#include <utility>
@@ -11,12 +11,24 @@
namespace mbgl {
namespace style {
RasterDEMSource::RasterDEMSource(std::string id, variant<std::string, Tileset> urlOrTileset_, uint16_t tileSize)
: RasterSource(std::move(id), std::move(urlOrTileset_), tileSize, SourceType::RasterDEM) {}
RasterDEMSource::RasterDEMSource(std::string id,
variant<std::string, Tileset> urlOrTileset_,
uint16_t tileSize,
std::optional<RasterDEMOptions> options_)
: RasterSource(std::move(id), std::move(urlOrTileset_), tileSize, SourceType::RasterDEM),
options(std::move(options_)) {}
bool RasterDEMSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const {
return mbgl::underlying_type(Tile::Kind::RasterDEM) == mbgl::underlying_type(info->tileKind);
}
void RasterDEMSource::setTilesetOverrides(Tileset& tileset) {
if (options) {
if (std::optional<Tileset::DEMEncoding> encoding = options.value().encoding) {
tileset.encoding = encoding.value();
}
}
}
} // namespace style
} // namespace mbgl

View File

@@ -4,7 +4,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source_observer.hpp>
#include <mbgl/style/sources/raster_source.hpp>
#include <mbgl/style/sources/raster_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/async_request.hpp>
#include <mbgl/util/exception.hpp>
@@ -17,85 +17,11 @@ RasterSource::RasterSource(std::string id,
variant<std::string, Tileset> urlOrTileset_,
uint16_t tileSize,
SourceType sourceType)
: Source(makeMutable<Impl>(sourceType, std::move(id), tileSize)),
urlOrTileset(std::move(urlOrTileset_)) {}
RasterSource::~RasterSource() = default;
const RasterSource::Impl& RasterSource::impl() const {
return static_cast<const Impl&>(*baseImpl);
}
const variant<std::string, Tileset>& RasterSource::getURLOrTileset() const {
return urlOrTileset;
}
std::optional<std::string> RasterSource::getURL() const {
if (urlOrTileset.is<Tileset>()) {
return {};
}
return urlOrTileset.get<std::string>();
}
uint16_t RasterSource::getTileSize() const {
return impl().getTileSize();
}
void RasterSource::loadDescription(FileSource& fileSource) {
if (urlOrTileset.is<Tileset>()) {
baseImpl = makeMutable<Impl>(impl(), urlOrTileset.get<Tileset>());
loaded = true;
observer->onSourceLoaded(*this);
return;
}
if (req) {
return;
}
const auto& rawURL = urlOrTileset.get<std::string>();
const auto& url = util::mapbox::canonicalizeSourceURL(fileSource.getResourceOptions().tileServerOptions(), rawURL);
req = fileSource.request(Resource::source(url), [this, url, &fileSource](const Response& res) {
if (res.error) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
} else if (res.notModified) {
return;
} else if (res.noContent) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
} else {
conversion::Error error;
std::optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data, error);
if (!tileset) {
observer->onSourceError(*this, std::make_exception_ptr(util::StyleParseException(error.message)));
return;
}
const auto& tileServerOptions = fileSource.getResourceOptions().tileServerOptions();
if (tileServerOptions.uriSchemeAlias() == "mapbox") {
util::mapbox::canonicalizeTileset(tileServerOptions, *tileset, url, getType(), getTileSize());
}
bool changed = impl().tileset != *tileset;
baseImpl = makeMutable<Impl>(impl(), *tileset);
loaded = true;
observer->onSourceLoaded(*this);
if (changed) {
observer->onSourceChanged(*this);
}
}
});
}
: TileSource(id, urlOrTileset_, tileSize, sourceType) {}
bool RasterSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const {
return mbgl::underlying_type(Tile::Kind::Raster) == mbgl::underlying_type(info->tileKind);
}
Mutable<Source::Impl> RasterSource::createMutable() const noexcept {
return staticMutableCast<Source::Impl>(makeMutable<Impl>(impl()));
}
} // namespace style
} // namespace mbgl

View File

@@ -0,0 +1,104 @@
#include <mbgl/storage/file_source.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source_observer.hpp>
#include <mbgl/style/sources/tile_source.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/async_request.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/mapbox.hpp>
namespace mbgl {
namespace style {
TileSource::TileSource(std::string id,
variant<std::string, Tileset> urlOrTileset_,
uint16_t tileSize,
SourceType sourceType)
: Source(makeMutable<Impl>(sourceType, std::move(id), tileSize)),
urlOrTileset(std::move(urlOrTileset_)) {}
TileSource::~TileSource() = default;
const TileSource::Impl& TileSource::impl() const {
return static_cast<const Impl&>(*baseImpl);
}
const variant<std::string, Tileset>& TileSource::getURLOrTileset() const {
return urlOrTileset;
}
std::optional<std::string> TileSource::getURL() const {
if (urlOrTileset.is<Tileset>()) {
return {};
}
return urlOrTileset.get<std::string>();
}
uint16_t TileSource::getTileSize() const {
return impl().getTileSize();
}
void TileSource::loadDescription(FileSource& fileSource) {
if (urlOrTileset.is<Tileset>()) {
baseImpl = makeMutable<Impl>(impl(), urlOrTileset.get<Tileset>());
loaded = true;
observer->onSourceLoaded(*this);
return;
}
if (req) {
return;
}
const auto& rawURL = urlOrTileset.get<std::string>();
const auto& url = util::mapbox::canonicalizeSourceURL(fileSource.getResourceOptions().tileServerOptions(), rawURL);
req = fileSource.request(Resource::source(url), [this, url, &fileSource](const Response& res) {
if (res.error) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
} else if (res.notModified) {
return;
} else if (res.noContent) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
} else {
conversion::Error error;
std::optional<Tileset> tileset = conversion::convertJSON<Tileset>(*res.data, error);
if (!tileset) {
observer->onSourceError(*this, std::make_exception_ptr(util::StyleParseException(error.message)));
return;
}
const auto& tileServerOptions = fileSource.getResourceOptions().tileServerOptions();
if (tileServerOptions.uriSchemeAlias() == "mapbox") {
util::mapbox::canonicalizeTileset(tileServerOptions, *tileset, url, getType(), getTileSize());
}
this->setTilesetOverrides(*tileset);
bool changed = impl().tileset != *tileset;
baseImpl = makeMutable<Impl>(impl(), *tileset);
loaded = true;
observer->onSourceLoaded(*this);
if (changed) {
observer->onSourceChanged(*this);
}
}
});
}
void TileSource::setTilesetOverrides(Tileset&) {
// Default empty implementation, subclasses can override
}
Mutable<Source::Impl> TileSource::createMutable() const noexcept {
return staticMutableCast<Source::Impl>(makeMutable<Impl>(impl()));
}
} // namespace style
} // namespace mbgl

View File

@@ -1,22 +1,22 @@
#include <mbgl/style/sources/raster_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
namespace mbgl {
namespace style {
RasterSource::Impl::Impl(SourceType sourceType, std::string id_, uint16_t tileSize_)
TileSource::Impl::Impl(SourceType sourceType, std::string id_, uint16_t tileSize_ = util::tileSize_I)
: Source::Impl(sourceType, std::move(id_)),
tileSize(tileSize_) {}
RasterSource::Impl::Impl(const Impl& other, Tileset tileset_)
TileSource::Impl::Impl(const Impl& other, Tileset tileset_)
: Source::Impl(other),
tileset(std::move(tileset_)),
tileSize(other.tileSize) {}
uint16_t RasterSource::Impl::getTileSize() const {
uint16_t TileSource::Impl::getTileSize() const {
return tileSize;
}
std::optional<std::string> RasterSource::Impl::getAttribution() const {
std::optional<std::string> TileSource::Impl::getAttribution() const {
if (!tileset) {
return {};
}

View File

@@ -1,12 +1,12 @@
#pragma once
#include <mbgl/style/sources/raster_source.hpp>
#include <mbgl/style/sources/tile_source.hpp>
#include <mbgl/style/source_impl.hpp>
namespace mbgl {
namespace style {
class RasterSource::Impl : public Source::Impl {
class TileSource::Impl : public Source::Impl {
public:
Impl(SourceType sourceType, std::string id, uint16_t tileSize);
Impl(const Impl&, Tileset);

View File

@@ -4,7 +4,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source_observer.hpp>
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/sources/vector_source_impl.hpp>
#include <mbgl/style/sources/tile_source_impl.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/async_request.hpp>
#include <mbgl/util/constants.hpp>
@@ -18,78 +18,17 @@ VectorSource::VectorSource(std::string id,
variant<std::string, Tileset> urlOrTileset_,
std::optional<float> maxZoom_,
std::optional<float> minZoom_)
: Source(makeMutable<Impl>(std::move(id))),
urlOrTileset(std::move(urlOrTileset_)),
: TileSource(id, urlOrTileset_, util::tileSize_I, SourceType::Vector),
maxZoom(std::move(maxZoom_)),
minZoom(std::move(minZoom_)) {}
VectorSource::~VectorSource() = default;
const VectorSource::Impl& VectorSource::impl() const {
return static_cast<const Impl&>(*baseImpl);
}
const variant<std::string, Tileset>& VectorSource::getURLOrTileset() const {
return urlOrTileset;
}
std::optional<std::string> VectorSource::getURL() const {
if (urlOrTileset.is<Tileset>()) {
return {};
void VectorSource::setTilesetOverrides(Tileset& tileset) {
if (maxZoom) {
tileset.zoomRange.max = static_cast<uint8_t>(*maxZoom);
}
return urlOrTileset.get<std::string>();
}
void VectorSource::loadDescription(FileSource& fileSource) {
if (urlOrTileset.is<Tileset>()) {
baseImpl = makeMutable<Impl>(impl(), urlOrTileset.get<Tileset>());
loaded = true;
observer->onSourceLoaded(*this);
return;
if (minZoom) {
tileset.zoomRange.min = static_cast<uint8_t>(*minZoom);
}
if (req) {
return;
}
const auto& rawURL = urlOrTileset.get<std::string>();
const auto& url = util::mapbox::canonicalizeSourceURL(fileSource.getResourceOptions().tileServerOptions(), rawURL);
req = fileSource.request(Resource::source(url), [this, url, &fileSource](const Response& res) {
if (res.error) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
} else if (res.notModified) {
return;
} else if (res.noContent) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
} else {
conversion::Error error;
auto tileset = conversion::convertJSON<Tileset>(*res.data, error);
if (!tileset) {
observer->onSourceError(*this, std::make_exception_ptr(util::StyleParseException(error.message)));
return;
}
if (maxZoom) {
tileset->zoomRange.max = static_cast<uint8_t>(*maxZoom);
}
if (minZoom) {
tileset->zoomRange.min = static_cast<uint8_t>(*minZoom);
}
const TileServerOptions& tileServerOptions = fileSource.getResourceOptions().tileServerOptions();
util::mapbox::canonicalizeTileset(tileServerOptions, *tileset, url, getType(), util::tileSize_I);
bool changed = impl().tileset != *tileset;
baseImpl = makeMutable<Impl>(impl(), *tileset);
loaded = true;
observer->onSourceLoaded(*this);
if (changed) {
observer->onSourceChanged(*this);
}
}
});
}
const std::vector<std::string> VectorSource::getTiles() const {
@@ -115,9 +54,5 @@ bool VectorSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) con
return mbgl::underlying_type(Tile::Kind::Geometry) == mbgl::underlying_type(info->tileKind);
}
Mutable<Source::Impl> VectorSource::createMutable() const noexcept {
return staticMutableCast<Source::Impl>(makeMutable<Impl>(impl()));
}
} // namespace style
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#include <mbgl/style/sources/vector_source_impl.hpp>
namespace mbgl {
namespace style {
VectorSource::Impl::Impl(std::string id_)
: Source::Impl(SourceType::Vector, std::move(id_)) {}
VectorSource::Impl::Impl(const Impl& other, Tileset tileset_)
: Source::Impl(other),
tileset(std::move(tileset_)) {}
std::optional<std::string> VectorSource::Impl::getAttribution() const {
if (!tileset) {
return {};
}
return tileset->attribution;
}
} // namespace style
} // namespace mbgl

View File

@@ -1,20 +0,0 @@
#pragma once
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/source_impl.hpp>
namespace mbgl {
namespace style {
class VectorSource::Impl : public Source::Impl {
public:
Impl(std::string id);
Impl(const Impl&, Tileset);
std::optional<std::string> getAttribution() const final;
const std::optional<Tileset> tileset;
};
} // namespace style
} // namespace mbgl

View File

@@ -51,6 +51,7 @@ add_library(
${PROJECT_SOURCE_DIR}/test/style/conversion/light.test.cpp
${PROJECT_SOURCE_DIR}/test/style/conversion/padding.test.cpp
${PROJECT_SOURCE_DIR}/test/style/conversion/property_value.test.cpp
${PROJECT_SOURCE_DIR}/test/style/conversion/raster_dem_options.test.cpp
${PROJECT_SOURCE_DIR}/test/style/conversion/stringify.test.cpp
${PROJECT_SOURCE_DIR}/test/style/conversion/tileset.test.cpp
${PROJECT_SOURCE_DIR}/test/style/expression/dependency.test.cpp

View File

@@ -0,0 +1,48 @@
#include <mbgl/test/util.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/raster_dem_options.hpp>
#include <mbgl/util/tileset.hpp>
#include <mbgl/util/logging.hpp>
using namespace mbgl;
using namespace mbgl::style;
using namespace mbgl::style::conversion;
TEST(RasterDEMOptions, Basic) {
Error error;
std::optional<RasterDEMOptions> converted = convertJSON<RasterDEMOptions>("{}", error);
ASSERT_TRUE((bool)converted);
}
TEST(RasterDEMOptions, ErrorHandling) {
Error error;
std::optional<RasterDEMOptions> converted = convertJSON<RasterDEMOptions>(
R"JSON({
"encoding": "this isn't a valid encoding"
})JSON",
error);
ASSERT_FALSE(converted);
ASSERT_EQ(error.message, "invalid raster-dem encoding type - valid types are 'mapbox' and 'terrarium'");
}
TEST(RasterDEMOptions, TerrariumEncodingParsed) {
Error error;
std::optional<RasterDEMOptions> converted = convertJSON<RasterDEMOptions>(
R"JSON({
"encoding": "terrarium"
})JSON",
error);
ASSERT_EQ(converted.value().encoding, Tileset::DEMEncoding::Terrarium);
}
TEST(RasterDEMOptions, MapboxEncodingParsed) {
Error error;
std::optional<RasterDEMOptions> converted = convertJSON<RasterDEMOptions>(
R"JSON({
"encoding": "mapbox"
})JSON",
error);
ASSERT_EQ(converted.value().encoding, Tileset::DEMEncoding::Mapbox);
}