diff --git a/.gitmodules b/.gitmodules index 18819c997..00db259d9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -100,6 +100,10 @@ [submodule "vendor/filesystem"] path = vendor/filesystem url = https://github.com/gulrak/filesystem.git +[submodule "vendor/maplibre-tile-spec"] + path = vendor/maplibre-tile-spec + url = https://github.com/maplibre/maplibre-tile-spec.git + branch = cpp [submodule "vendor/kdbush.hpp"] path = vendor/kdbush.hpp url = https://github.com/mourner/kdbush.hpp.git diff --git a/BUILD.bazel b/BUILD.bazel index 0fadb0c43..dd71e0f47 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -144,6 +144,7 @@ cc_library( "//vendor:eternal", "//vendor:expected-lite", "//vendor:maplibre-native-base", + "//vendor/maplibre-tile-spec/cpp:mlt_cpp", "//vendor:parsedate", "//vendor:pmtiles", "//vendor:polylabel", diff --git a/CMakeLists.txt b/CMakeLists.txt index b768f3442..afdb84b16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -302,9 +302,9 @@ 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/source_options.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/tileset.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/conversion/transition_options.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/expression/assertion.hpp @@ -676,9 +676,9 @@ 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/source_options.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/stringify.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/tileset.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/transition_options.cpp @@ -879,10 +879,15 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_operation.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_tile.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_tile.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_tile_data.cpp - ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_tile_data.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mlt_tile.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mlt_tile.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mlt_tile_data.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mlt_tile_data.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mvt_tile.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mvt_tile.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mvt_tile_data.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_mvt_tile_data.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/action_journal.cpp - ${PROJECT_SOURCE_DIR}/src/mbgl/util/action_journal_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/action_journal_impl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/camera.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/bounding_volumes.hpp @@ -1553,6 +1558,7 @@ include(${PROJECT_SOURCE_DIR}/vendor/unordered_dense.cmake) include(${PROJECT_SOURCE_DIR}/vendor/vector-tile.cmake) include(${PROJECT_SOURCE_DIR}/vendor/wagyu.cmake) include(${PROJECT_SOURCE_DIR}/vendor/metal-cpp.cmake) +include(${PROJECT_SOURCE_DIR}/vendor/maplibre-tile-spec.cmake) include(${PROJECT_SOURCE_DIR}/vendor/supercluster.cmake) include(${PROJECT_SOURCE_DIR}/vendor/expected-lite.cmake) include(${PROJECT_SOURCE_DIR}/vendor/kdbush.cmake) @@ -1581,6 +1587,7 @@ target_link_libraries( mbgl-vendor-unique_resource mbgl-vendor-vector-tile mbgl-vendor-wagyu + mlt-cpp $<$:mbgl-vendor-metal-cpp> $,mbgl-rustutils,mbgl-vendor-csscolorparser> $<$:mbgl-freetype> @@ -1614,6 +1621,8 @@ set(EXPORT_TARGETS mbgl-vendor-boost mbgl-vendor-earcut.hpp mbgl-vendor-eternal + mbgl-vendor-filesystem + mbgl-vendor-metal-cpp mbgl-vendor-rapidjson mbgl-vendor-parsedate mbgl-vendor-pmtiles @@ -1622,8 +1631,7 @@ set(EXPORT_TARGETS mbgl-vendor-unique_resource mbgl-vendor-vector-tile mbgl-vendor-wagyu - mbgl-vendor-metal-cpp - mbgl-vendor-filesystem + mlt-cpp unordered_dense ) diff --git a/bazel/core.bzl b/bazel/core.bzl index 6271e28ad..fe4ba981b 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -336,9 +336,9 @@ 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/source_options.cpp", "src/mbgl/style/conversion/stringify.hpp", "src/mbgl/style/conversion/tileset.cpp", "src/mbgl/style/conversion/transition_options.cpp", @@ -514,8 +514,14 @@ MLN_CORE_SOURCE = [ "src/mbgl/tile/tile_operation.cpp", "src/mbgl/tile/vector_tile.cpp", "src/mbgl/tile/vector_tile.hpp", - "src/mbgl/tile/vector_tile_data.cpp", - "src/mbgl/tile/vector_tile_data.hpp", + "src/mbgl/tile/vector_mlt_tile.cpp", + "src/mbgl/tile/vector_mlt_tile.hpp", + "src/mbgl/tile/vector_mlt_tile_data.cpp", + "src/mbgl/tile/vector_mlt_tile_data.hpp", + "src/mbgl/tile/vector_mvt_tile.cpp", + "src/mbgl/tile/vector_mvt_tile.hpp", + "src/mbgl/tile/vector_mvt_tile_data.cpp", + "src/mbgl/tile/vector_mvt_tile_data.hpp", "src/mbgl/util/action_journal.cpp", "src/mbgl/util/action_journal_impl.hpp", "src/mbgl/util/action_journal_impl.cpp", @@ -696,9 +702,9 @@ 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/source_options.hpp", "include/mbgl/style/conversion/tileset.hpp", "include/mbgl/style/conversion/transition_options.hpp", "include/mbgl/style/conversion_impl.hpp", diff --git a/benchmark/parse/vector_tile.benchmark.cpp b/benchmark/parse/vector_tile.benchmark.cpp index 35f11e9c7..a7eaa0955 100644 --- a/benchmark/parse/vector_tile.benchmark.cpp +++ b/benchmark/parse/vector_tile.benchmark.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include using namespace mbgl; @@ -11,7 +11,7 @@ static void Parse_VectorTile(benchmark::State& state) { while (state.KeepRunning()) { std::size_t length = 0; - VectorTileData tile(data); + VectorMVTTileData tile(data); for (const auto& name : tile.layerNames()) { if (auto layer = tile.getLayer(name)) { const std::size_t count = layer->featureCount(); diff --git a/bin/cache.cpp b/bin/cache.cpp index 179cd9dc8..d78ccd212 100644 --- a/bin/cache.cpp +++ b/bin/cache.cpp @@ -7,14 +7,13 @@ #include #include -#include #include #include #include #include int main(int argc, char* argv[]) { - args::ArgumentParser p("Mapbox GL cache tool", ""); + args::ArgumentParser p("MapLibre cache tool", ""); args::HelpFlag helpFlag(p, "help", "Display this help menu", {'h'}); args::ValueFlag urlValue(p, "URL", "Resource URL (required)", {'u'}, args::Options::Required); @@ -35,7 +34,7 @@ int main(int argc, char* argv[]) { {"tile", mbgl::Resource::Tile}}; std::string typeHelp("One of the following (required):"); - for (auto key : typeMap) { + for (const auto& key : typeMap) { typeHelp += " " + key.first; } @@ -53,18 +52,18 @@ int main(int argc, char* argv[]) { std::cout << p; exit(0); } catch (const args::ParseError& e) { - std::cerr << e.what() << std::endl; + std::cerr << e.what() << '\n'; std::cerr << p; exit(1); } catch (const args::ValidationError& e) { - std::cerr << e.what() << std::endl; + std::cerr << e.what() << '\n'; std::cerr << p; exit(2); } auto file = mapbox::base::io::readFile(args::get(dataValue)); if (!file) { - std::cerr << file.error() << std::endl; + std::cerr << file.error() << '\n'; exit(3); } @@ -78,15 +77,15 @@ int main(int argc, char* argv[]) { if (args::get(typeFlag) == mbgl::Resource::Tile) { if (!xValueFlag || !yValueFlag || !zValueFlag) { - std::cerr << "Error: -x, -y and -z must be provided for tiles" << std::endl; + std::cerr << "Error: -x, -y and -z must be provided for tiles" << '\n'; exit(1); } - resource.tileData = {{args::get(urlValue), - 1, - args::get(xValueFlag), - args::get(yValueFlag), - static_cast(args::get(zValueFlag))}}; + resource.tileData = {{.urlTemplate = args::get(urlValue), + .pixelRatio = 1, + .x = args::get(xValueFlag), + .y = args::get(yValueFlag), + .z = static_cast(args::get(zValueFlag))}}; } mbgl::util::RunLoop loop; diff --git a/include/mbgl/style/conversion/raster_dem_options.hpp b/include/mbgl/style/conversion/source_options.hpp similarity index 65% rename from include/mbgl/style/conversion/raster_dem_options.hpp rename to include/mbgl/style/conversion/source_options.hpp index 5962dbba0..1f91d9b97 100644 --- a/include/mbgl/style/conversion/raster_dem_options.hpp +++ b/include/mbgl/style/conversion/source_options.hpp @@ -8,8 +8,8 @@ namespace style { namespace conversion { template <> -struct Converter { - std::optional operator()(const Convertible& value, Error& error) const; +struct Converter { + std::optional operator()(const Convertible& value, Error& error) const; }; } // namespace conversion diff --git a/include/mbgl/style/sources/raster_dem_source.hpp b/include/mbgl/style/sources/raster_dem_source.hpp index a2a612eac..5e7ee0e2b 100644 --- a/include/mbgl/style/sources/raster_dem_source.hpp +++ b/include/mbgl/style/sources/raster_dem_source.hpp @@ -7,8 +7,9 @@ namespace mbgl { namespace style { -struct RasterDEMOptions { - std::optional encoding = std::nullopt; +struct SourceOptions { + std::optional rasterEncoding = std::nullopt; + std::optional vectorEncoding = std::nullopt; }; // NOTE: Any derived class must invalidate `weakFactory` in the destructor @@ -17,7 +18,7 @@ public: RasterDEMSource(std::string id, variant urlOrTileset, uint16_t tileSize, - std::optional options = std::nullopt); + std::optional options = std::nullopt); ~RasterDEMSource() override; bool supportsLayerType(const mbgl::style::LayerTypeInfo*) const override; @@ -25,7 +26,7 @@ protected: void setTilesetOverrides(Tileset& tileset) override; private: - std::optional options; + std::optional options; }; template <> diff --git a/include/mbgl/style/sources/vector_source.hpp b/include/mbgl/style/sources/vector_source.hpp index e02f8e75b..37cdc1917 100644 --- a/include/mbgl/style/sources/vector_source.hpp +++ b/include/mbgl/style/sources/vector_source.hpp @@ -16,7 +16,8 @@ public: VectorSource(std::string id, variant urlOrTileset, std::optional maxZoom = std::nullopt, - std::optional minZoom = std::nullopt); + std::optional minZoom = std::nullopt, + Tileset::VectorEncoding encoding = Tileset::VectorEncoding::Mapbox); void setTilesetOverrides(Tileset& tileset) override; @@ -30,11 +31,14 @@ public: bool supportsLayerType(const mbgl::style::LayerTypeInfo*) const override; + Tileset::VectorEncoding getEncoding() const noexcept { return encoding; } + mapbox::base::WeakPtr makeWeakPtr() override { return weakFactory.makeWeakPtr(); } private: std::optional maxZoom; std::optional minZoom; + Tileset::VectorEncoding encoding; mapbox::base::WeakPtrFactory weakFactory{this}; // Must remain last }; diff --git a/include/mbgl/util/tileset.hpp b/include/mbgl/util/tileset.hpp index d2fd0b811..cf60b366e 100644 --- a/include/mbgl/util/tileset.hpp +++ b/include/mbgl/util/tileset.hpp @@ -18,38 +18,40 @@ public: XYZ, TMS }; - enum class DEMEncoding : bool { - Mapbox, - Terrarium + enum class RasterEncoding : std::uint8_t { + Mapbox, // Mapbox DEM + Terrarium, // Terrarium DEM + }; + enum class VectorEncoding : std::uint8_t { + Mapbox, // Mapbox Vector Tiles (MVT) + MLT, // MapLibre Tiles }; std::vector tiles; Range zoomRange; std::string attribution; Scheme scheme; - // DEMEncoding is not supported by the TileJSON spec - DEMEncoding encoding; + std::optional rasterEncoding; + std::optional vectorEncoding; std::optional bounds; Tileset(std::vector tiles_ = std::vector(), Range zoomRange_ = {0, util::DEFAULT_MAX_ZOOM}, std::string attribution_ = {}, Scheme scheme_ = Scheme::XYZ, - DEMEncoding encoding_ = DEMEncoding::Mapbox) + std::optional rasterEncoding_ = std::nullopt, + std::optional encoding_ = std::nullopt) : tiles(std::move(tiles_)), zoomRange(zoomRange_), attribution(std::move(attribution_)), scheme(scheme_), - encoding(encoding_) {}; + rasterEncoding(rasterEncoding_), + vectorEncoding(encoding_) {} // TileJSON also includes center and zoom but they are not used by mbgl. - friend bool operator==(const Tileset& lhs, const Tileset& rhs) noexcept { - return std::tie(lhs.tiles, lhs.zoomRange, lhs.attribution, lhs.scheme, lhs.bounds) == - std::tie(rhs.tiles, rhs.zoomRange, rhs.attribution, rhs.scheme, rhs.bounds); - } - - friend bool operator!=(const Tileset& lhs, const Tileset& rhs) noexcept { return !(lhs == rhs); } + bool operator==(const Tileset&) const = default; + bool operator!=(const Tileset&) const = default; }; } // namespace mbgl diff --git a/metrics/cache-style.db b/metrics/cache-style.db index 78ad6c13c..11658f275 100644 Binary files a/metrics/cache-style.db and b/metrics/cache-style.db differ diff --git a/metrics/integration/render-tests/extent/1024-symbol/style.json b/metrics/integration/render-tests/extent/1024-symbol/style.json index 9677b54dc..1b91f76e8 100644 --- a/metrics/integration/render-tests/extent/1024-symbol/style.json +++ b/metrics/integration/render-tests/extent/1024-symbol/style.json @@ -2,7 +2,13 @@ "version": 8, "metadata": { "test": { - "allowed": 0.003 + "allowed": 0.003, + "source-replace": [ + { + "replace": "maplibre", + "with": "mlt" + } + ] } }, "center": [ @@ -19,6 +25,14 @@ "tiles": [ "local://tiles/extent1024-14-8802-5374.mvt" ] + }, + "mlt": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/extent1024-14-8802-5374.mlt" + ], + "encoding": "mlt" } }, "layers": [ diff --git a/metrics/integration/render-tests/fill-pattern/wrapping-with-interpolation/style.json b/metrics/integration/render-tests/fill-pattern/wrapping-with-interpolation/style.json index 65044fce9..6fb6bb6b9 100644 --- a/metrics/integration/render-tests/fill-pattern/wrapping-with-interpolation/style.json +++ b/metrics/integration/render-tests/fill-pattern/wrapping-with-interpolation/style.json @@ -1,7 +1,14 @@ { "version": 8, "metadata": { - "test": {} + "test": { + "source-replace": [ + { + "replace": "maplibre", + "with": "mlt" + } + ] + } }, "zoom": 0.99, "center": [ @@ -15,6 +22,14 @@ "tiles": [ "local://tiles/{z}-{x}-{y}.mvt" ] + }, + "mlt": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mlt" + ], + "encoding": "mlt" } }, "sprite": "local://sprites/solid-black", diff --git a/metrics/integration/render-tests/icon-visibility/visible/style.json b/metrics/integration/render-tests/icon-visibility/visible/style.json index 059607574..60a3f733e 100644 --- a/metrics/integration/render-tests/icon-visibility/visible/style.json +++ b/metrics/integration/render-tests/icon-visibility/visible/style.json @@ -2,7 +2,11 @@ "version": 8, "metadata": { "test": { - "height": 256 + "height": 256, + "source-replace": [{ + "replace": "maplibre", + "with": "mlt" + }] } }, "center": [ @@ -17,6 +21,14 @@ "tiles": [ "local://tiles/{z}-{x}-{y}.mvt" ] + }, + "mlt": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mlt" + ], + "encoding": "mlt" } }, "sprite": "local://sprites/sprite", diff --git a/metrics/integration/render-tests/text-pitch-alignment/viewport-overzoomed-single-glyph/style.json b/metrics/integration/render-tests/text-pitch-alignment/viewport-overzoomed-single-glyph/style.json index 060feb81e..f612425f5 100644 --- a/metrics/integration/render-tests/text-pitch-alignment/viewport-overzoomed-single-glyph/style.json +++ b/metrics/integration/render-tests/text-pitch-alignment/viewport-overzoomed-single-glyph/style.json @@ -1,5 +1,15 @@ { "version": 8, + "metadata": { + "test": { + "source-replace": [ + { + "replace": "maplibre", + "with": "mlt" + } + ] + } + }, "center": [ -118.28162, 33.86852 @@ -14,6 +24,14 @@ "tiles": [ "local://tiles/mapbox.mapbox-streets-v7/16-11235-26208.mvt" ] + }, + "mlt": { + "type": "vector", + "maxzoom": 16, + "tiles": [ + "local://tiles/mapbox.mapbox-streets-v7/16-11235-26208.mlt" + ], + "encoding": "mlt" } }, "glyphs": "local://glyphs/{fontstack}/{range}.pbf", diff --git a/metrics/integration/render-tests/tms/tms/style.json b/metrics/integration/render-tests/tms/tms/style.json index 349e3167e..3d93247b7 100644 --- a/metrics/integration/render-tests/tms/tms/style.json +++ b/metrics/integration/render-tests/tms/tms/style.json @@ -1,7 +1,14 @@ { "version": 8, "metadata": { - "test": {} + "test": { + "source-replace": [ + { + "replace": "maplibre", + "with": "mlt" + } + ] + } }, "zoom": 2, "sources": { @@ -12,6 +19,15 @@ "tiles": [ "local://tiles/{z}-{x}-{y}.tms.mvt" ] + }, + "mlt": { + "type": "vector", + "maxzoom": 14, + "scheme": "tms", + "tiles": [ + "local://tiles/{z}-{x}-{y}.tms.mlt" + ], + "encoding": "mlt" } }, "layers": [ diff --git a/metrics/integration/tiles/0-0-0.mlt b/metrics/integration/tiles/0-0-0.mlt new file mode 100644 index 000000000..441d3e3e5 Binary files /dev/null and b/metrics/integration/tiles/0-0-0.mlt differ diff --git a/metrics/integration/tiles/14-4357-6245.mlt b/metrics/integration/tiles/14-4357-6245.mlt new file mode 100644 index 000000000..291cc538b Binary files /dev/null and b/metrics/integration/tiles/14-4357-6245.mlt differ diff --git a/metrics/integration/tiles/14-8802-5374.mlt b/metrics/integration/tiles/14-8802-5374.mlt new file mode 100644 index 000000000..540a3e8dc Binary files /dev/null and b/metrics/integration/tiles/14-8802-5374.mlt differ diff --git a/metrics/integration/tiles/14-8802-5375.mlt b/metrics/integration/tiles/14-8802-5375.mlt new file mode 100644 index 000000000..762a09c5c Binary files /dev/null and b/metrics/integration/tiles/14-8802-5375.mlt differ diff --git a/metrics/integration/tiles/14-8803-5374.mlt b/metrics/integration/tiles/14-8803-5374.mlt new file mode 100644 index 000000000..6b264897c Binary files /dev/null and b/metrics/integration/tiles/14-8803-5374.mlt differ diff --git a/metrics/integration/tiles/14-8803-5375.mlt b/metrics/integration/tiles/14-8803-5375.mlt new file mode 100644 index 000000000..2ba832ceb Binary files /dev/null and b/metrics/integration/tiles/14-8803-5375.mlt differ diff --git a/metrics/integration/tiles/2-1-1.mlt b/metrics/integration/tiles/2-1-1.mlt new file mode 100644 index 000000000..f37f8fddb Binary files /dev/null and b/metrics/integration/tiles/2-1-1.mlt differ diff --git a/metrics/integration/tiles/2-1-1.tms.mlt b/metrics/integration/tiles/2-1-1.tms.mlt new file mode 100644 index 000000000..66bfbe908 Binary files /dev/null and b/metrics/integration/tiles/2-1-1.tms.mlt differ diff --git a/metrics/integration/tiles/2-1-2.mlt b/metrics/integration/tiles/2-1-2.mlt new file mode 100644 index 000000000..66bfbe908 Binary files /dev/null and b/metrics/integration/tiles/2-1-2.mlt differ diff --git a/metrics/integration/tiles/2-1-2.tms.mlt b/metrics/integration/tiles/2-1-2.tms.mlt new file mode 100644 index 000000000..f37f8fddb Binary files /dev/null and b/metrics/integration/tiles/2-1-2.tms.mlt differ diff --git a/metrics/integration/tiles/2-2-1.mlt b/metrics/integration/tiles/2-2-1.mlt new file mode 100644 index 000000000..281d271e2 Binary files /dev/null and b/metrics/integration/tiles/2-2-1.mlt differ diff --git a/metrics/integration/tiles/2-2-1.tms.mlt b/metrics/integration/tiles/2-2-1.tms.mlt new file mode 100644 index 000000000..66e5ba0de Binary files /dev/null and b/metrics/integration/tiles/2-2-1.tms.mlt differ diff --git a/metrics/integration/tiles/2-2-2.mlt b/metrics/integration/tiles/2-2-2.mlt new file mode 100644 index 000000000..66e5ba0de Binary files /dev/null and b/metrics/integration/tiles/2-2-2.mlt differ diff --git a/metrics/integration/tiles/2-2-2.tms.mlt b/metrics/integration/tiles/2-2-2.tms.mlt new file mode 100644 index 000000000..281d271e2 Binary files /dev/null and b/metrics/integration/tiles/2-2-2.tms.mlt differ diff --git a/metrics/integration/tiles/counties-7-37-48.mlt b/metrics/integration/tiles/counties-7-37-48.mlt new file mode 100644 index 000000000..2643924d7 Binary files /dev/null and b/metrics/integration/tiles/counties-7-37-48.mlt differ diff --git a/metrics/integration/tiles/extent1024-14-8802-5374.mlt b/metrics/integration/tiles/extent1024-14-8802-5374.mlt new file mode 100644 index 000000000..540a3e8dc Binary files /dev/null and b/metrics/integration/tiles/extent1024-14-8802-5374.mlt differ diff --git a/metrics/integration/tiles/mapbox.mapbox-streets-v7/0-0-0.mlt b/metrics/integration/tiles/mapbox.mapbox-streets-v7/0-0-0.mlt new file mode 100644 index 000000000..981630016 Binary files /dev/null and b/metrics/integration/tiles/mapbox.mapbox-streets-v7/0-0-0.mlt differ diff --git a/metrics/integration/tiles/mapbox.mapbox-streets-v7/10-175-409.mlt b/metrics/integration/tiles/mapbox.mapbox-streets-v7/10-175-409.mlt new file mode 100644 index 000000000..b914c4aa4 Binary files /dev/null and b/metrics/integration/tiles/mapbox.mapbox-streets-v7/10-175-409.mlt differ diff --git a/metrics/integration/tiles/mapbox.mapbox-streets-v7/11-351-818.mlt b/metrics/integration/tiles/mapbox.mapbox-streets-v7/11-351-818.mlt new file mode 100644 index 000000000..5ec10c371 Binary files /dev/null and b/metrics/integration/tiles/mapbox.mapbox-streets-v7/11-351-818.mlt differ diff --git a/metrics/integration/tiles/mapbox.mapbox-streets-v7/16-11235-26208.mlt b/metrics/integration/tiles/mapbox.mapbox-streets-v7/16-11235-26208.mlt new file mode 100644 index 000000000..d23d74e77 Binary files /dev/null and b/metrics/integration/tiles/mapbox.mapbox-streets-v7/16-11235-26208.mlt differ diff --git a/metrics/integration/tiles/mapbox.mapbox-streets-v7/4-4-7.mlt b/metrics/integration/tiles/mapbox.mapbox-streets-v7/4-4-7.mlt new file mode 100644 index 000000000..0253d90f7 Binary files /dev/null and b/metrics/integration/tiles/mapbox.mapbox-streets-v7/4-4-7.mlt differ diff --git a/metrics/integration/tiles/mapbox.mapbox-streets-v7/4-5-7.mlt b/metrics/integration/tiles/mapbox.mapbox-streets-v7/4-5-7.mlt new file mode 100644 index 000000000..bd955c9f1 Binary files /dev/null and b/metrics/integration/tiles/mapbox.mapbox-streets-v7/4-5-7.mlt differ diff --git a/platform/darwin/src/MLNRasterDEMSource.h b/platform/darwin/src/MLNRasterDEMSource.h index 5793ca0ed..71a3862bf 100644 --- a/platform/darwin/src/MLNRasterDEMSource.h +++ b/platform/darwin/src/MLNRasterDEMSource.h @@ -10,11 +10,30 @@ The default value for this option is ``MLNDEMEncoding/MLNDEMEncodingMapbox``. This option cannot be represented in a TileJSON or style JSON file. It is used - with the ``MLNRasterDEMSource`` class and is ignored when creating an + with the ``MLNRasterDEMSource`` class and is ignored when creating a ``MLNRasterTileSource`` or ``MLNRasterTileSource`` object. */ FOUNDATION_EXTERN MLN_EXPORT const MLNTileSourceOption MLNTileSourceOptionDEMEncoding; +/** + The encoding formula used to generate the raster tileset +*/ + +typedef NS_ENUM(NSUInteger, MLNDEMEncoding) { + + /** + Raster tiles generated with the [Mapbox encoding + formula](https://docs.mapbox.com/help/troubleshooting/access-elevation-data/#mapbox-terrain-rgb) + */ + MLNDEMEncodingMapbox = 0, + + /** + Raster tiles generated with the [Mapzen Terrarium encoding + formula](https://aws.amazon.com/public-datasets/terrain/). + */ + MLNDEMEncodingTerrarium = 1, +}; + /** ``MLNRasterDEMSource`` is a map content source that supplies rasterized digital elevation model diff --git a/platform/darwin/src/MLNRasterDEMSource.mm b/platform/darwin/src/MLNRasterDEMSource.mm index 13ad81602..be2e34b13 100644 --- a/platform/darwin/src/MLNRasterDEMSource.mm +++ b/platform/darwin/src/MLNRasterDEMSource.mm @@ -5,6 +5,8 @@ #import +const MLNTileSourceOption MLNTileSourceOptionDEMEncoding = @"MLNTileSourceOptionDEMEncoding"; + @implementation MLNRasterDEMSource - (std::unique_ptr)pendingSourceWithIdentifier:(NSString *)identifier urlOrTileset:(mbgl::variant)urlOrTileset tileSize:(uint16_t)tileSize { diff --git a/platform/darwin/src/MLNTileSource.h b/platform/darwin/src/MLNTileSource.h index 9ea6b0bcd..445ad622c 100644 --- a/platform/darwin/src/MLNTileSource.h +++ b/platform/darwin/src/MLNTileSource.h @@ -142,25 +142,6 @@ typedef NS_ENUM(NSUInteger, MLNTileCoordinateSystem) { MLNTileCoordinateSystemTMS }; -/** - The encoding formula used to generate the raster-dem tileset -*/ - -typedef NS_ENUM(NSUInteger, MLNDEMEncoding) { - - /** - Raster tiles generated with the [Mapbox encoding - formula](https://docs.mapbox.com/help/troubleshooting/access-elevation-data/#mapbox-terrain-rgb). - */ - MLNDEMEncodingMapbox = 0, - - /** - Raster tiles generated with the [Mapzen Terrarium encoding - formula](https://aws.amazon.com/public-datasets/terrain/). - */ - MLNDEMEncodingTerrarium -}; - /** ``MLNTileSource`` is a map content source that supplies map tiles to be shown on the map. The location of and metadata about the tiles are defined either by an diff --git a/platform/darwin/src/MLNTileSource.mm b/platform/darwin/src/MLNTileSource.mm index 5752c4c39..425f83408 100644 --- a/platform/darwin/src/MLNTileSource.mm +++ b/platform/darwin/src/MLNTileSource.mm @@ -3,6 +3,7 @@ #import "MLNAttributionInfo_Private.h" #import "MLNGeometry_Private.h" #import "MLNRasterDEMSource.h" +#import "MLNVectorTileSource.h" #import "NSString+MLNAdditions.h" #import "NSValue+MLNAdditions.h" @@ -20,7 +21,6 @@ const MLNTileSourceOption MLNTileSourceOptionCoordinateBounds = @"MLNTileSourceO const MLNTileSourceOption MLNTileSourceOptionAttributionHTMLString = @"MLNTileSourceOptionAttributionHTMLString"; const MLNTileSourceOption MLNTileSourceOptionAttributionInfos = @"MLNTileSourceOptionAttributionInfos"; const MLNTileSourceOption MLNTileSourceOptionTileCoordinateSystem = @"MLNTileSourceOptionTileCoordinateSystem"; -const MLNTileSourceOption MLNTileSourceOptionDEMEncoding = @"MLNTileSourceOptionDEMEncoding"; @implementation MLNTileSource @@ -131,19 +131,38 @@ mbgl::Tileset MLNTileSetFromTileURLTemplates(NSArray *tileURLTemplat } } - if (NSNumber *demEncodingNumber = options[MLNTileSourceOptionDEMEncoding]) { - if (![demEncodingNumber isKindOfClass:[NSValue class]]) { + NSNumber *encodingNumber = options[MLNTileSourceOptionDEMEncoding]; + if (encodingNumber) { + if (![encodingNumber isKindOfClass:[NSValue class]]) { [NSException raise:NSInvalidArgumentException format:@"MLNTileSourceOptionDEMEncoding must be set to an NSValue or NSNumber."]; } - MLNDEMEncoding demEncoding; - [demEncodingNumber getValue:&demEncoding]; - switch (demEncoding) { + MLNDEMEncoding encoding; + [encodingNumber getValue:&encoding]; + switch (encoding) { case MLNDEMEncodingMapbox: - tileSet.encoding = mbgl::Tileset::DEMEncoding::Mapbox; + tileSet.rasterEncoding = mbgl::Tileset::RasterEncoding::Mapbox; break; case MLNDEMEncodingTerrarium: - tileSet.encoding = mbgl::Tileset::DEMEncoding::Terrarium; + tileSet.rasterEncoding = mbgl::Tileset::RasterEncoding::Terrarium; + break; + } + } + + encodingNumber = options[MLNVectorTileSourceOptionEncoding]; + if (encodingNumber) { + if (![encodingNumber isKindOfClass:[NSValue class]]) { + [NSException raise:NSInvalidArgumentException + format:@"MLNTileSourceOptionVectorEncoding must be set to an NSValue or NSNumber."]; + } + MLNVectorTileSourceEncoding encoding; + [encodingNumber getValue:&encoding]; + switch (encoding) { + case MLNVectorTileSourceEncodingMapbox: + tileSet.vectorEncoding = mbgl::Tileset::VectorEncoding::Mapbox; + break; + case MLNVectorTileSourceEncodingMLT: + tileSet.vectorEncoding = mbgl::Tileset::VectorEncoding::MLT; break; } } diff --git a/platform/darwin/src/MLNVectorTileSource.h b/platform/darwin/src/MLNVectorTileSource.h index a3c807b49..e120febfd 100644 --- a/platform/darwin/src/MLNVectorTileSource.h +++ b/platform/darwin/src/MLNVectorTileSource.h @@ -4,6 +4,33 @@ NS_ASSUME_NONNULL_BEGIN +/** + An `NSNumber` object containing an unsigned integer that specifies the encoding + formula for vector tilesets. The integer corresponds to one of the constants in + ``MLNVectorTileSourceEncoding``. + + The default value for this option is + ``MLNVectorTileSourceEncoding/MLNVectorTileSourceEncodingMapbox``. + */ +FOUNDATION_EXTERN MLN_EXPORT const MLNTileSourceOption MLNVectorTileSourceOptionEncoding; + +/** + The encoding formula used to generate the raster-dem tileset +*/ + +typedef NS_ENUM(NSUInteger, MLNVectorTileSourceEncoding) { + + /** + Vector tiles in [MVT format](https://github.com/mapbox/vector-tile-spec). + */ + MLNVectorTileSourceEncodingMapbox = 0, + + /** + Vector tiles in [MLT format](https://github.com/maplibre/maplibre-tile-spec). + */ + MLNVectorTileSourceEncodingMLT = 1, +}; + /** ``MLNVectorTileSource`` is a map content source that supplies tiled vector data in Mapbox Vector Tile format diff --git a/platform/darwin/src/MLNVectorTileSource.mm b/platform/darwin/src/MLNVectorTileSource.mm index 6c2413f2f..d63a4a9fe 100644 --- a/platform/darwin/src/MLNVectorTileSource.mm +++ b/platform/darwin/src/MLNVectorTileSource.mm @@ -14,6 +14,8 @@ #include #include +const MLNTileSourceOption MLNVectorTileSourceOptionEncoding = @"MLNVectorTileSourceOptionEncoding"; + @interface MLNVectorTileSource () @property (nonatomic, readonly) mbgl::style::VectorSource *rawSource; diff --git a/platform/darwin/test/MLNTileSetTests.mm b/platform/darwin/test/MLNTileSetTests.mm index 8c2865cc5..25d35b2f5 100644 --- a/platform/darwin/test/MLNTileSetTests.mm +++ b/platform/darwin/test/MLNTileSetTests.mm @@ -1,6 +1,7 @@ #import #import +#import "MLNVectorTileSource.h" #import "MLNTileSource_Private.h" #import "MLNGeometry_Private.h" @@ -12,9 +13,13 @@ @implementation MLNTileSetTests -- (void)testTileSetFromTileURLTemplates { +namespace { // a tile set that provides an mbgl tile set NSArray *tileURLTemplates = @[@"tile.1", @"tile.2", @"tile.3"]; + +} + +- (void)testTileSetFromTileURLTemplates { mbgl::Tileset tileSet = MLNTileSetFromTileURLTemplates(tileURLTemplates, nil); // has the correct URL templates @@ -120,23 +125,61 @@ // the scheme is reflected by the mbgl tileset XCTAssertEqual(tileSet.scheme, mbgl::Tileset::Scheme::TMS); +} - // when the dem encoding is changed using an NSNumber +- (void)testTileSetFromTileURLTemplatesRasterEncodings { + mbgl::Tileset tileSet; + + // when the DEM encoding is changed using an NSNumber tileSet = MLNTileSetFromTileURLTemplates(tileURLTemplates, @{ MLNTileSourceOptionDEMEncoding: @(MLNDEMEncodingTerrarium), }); // the encoding is reflected by the mbgl tileset - XCTAssertEqual(tileSet.encoding, mbgl::Tileset::DEMEncoding::Terrarium); + XCTAssertEqual(tileSet.rasterEncoding, mbgl::Tileset::RasterEncoding::Terrarium); + XCTAssertFalse(tileSet.vectorEncoding); - // when the dem encoding is changed using an NSValue + // when the raster encoding is changed using an NSValue MLNDEMEncoding terrarium = MLNDEMEncodingTerrarium; tileSet = MLNTileSetFromTileURLTemplates(tileURLTemplates, @{ MLNTileSourceOptionDEMEncoding: [NSValue value:&terrarium withObjCType:@encode(MLNDEMEncoding)], }); // the encoding is reflected by the mbgl tileset - XCTAssertEqual(tileSet.encoding, mbgl::Tileset::DEMEncoding::Terrarium); + XCTAssertEqual(tileSet.rasterEncoding, mbgl::Tileset::RasterEncoding::Terrarium); + XCTAssertFalse(tileSet.vectorEncoding); +} + +- (void)testTileSetFromTileURLTemplatesVectorEncodings { + mbgl::Tileset tileSet; + + // when the raster encoding is changed using an NSNumber + tileSet = MLNTileSetFromTileURLTemplates(tileURLTemplates, @{ + MLNVectorTileSourceOptionEncoding: @(MLNVectorTileSourceEncodingMapbox), + }); + + // the encoding is reflected by the mbgl tileset + XCTAssertEqual(tileSet.vectorEncoding, mbgl::Tileset::VectorEncoding::Mapbox); + XCTAssertFalse(tileSet.rasterEncoding); + + // when the raster encoding is changed using an NSNumber + tileSet = MLNTileSetFromTileURLTemplates(tileURLTemplates, @{ + MLNVectorTileSourceOptionEncoding: @(MLNVectorTileSourceEncodingMLT), + }); + + // the encoding is reflected by the mbgl tileset + XCTAssertEqual(tileSet.vectorEncoding, mbgl::Tileset::VectorEncoding::MLT); + XCTAssertFalse(tileSet.rasterEncoding); + + // when the raster encoding is changed using an NSValue + MLNVectorTileSourceEncoding mlt = MLNVectorTileSourceEncodingMLT; + tileSet = MLNTileSetFromTileURLTemplates(tileURLTemplates, @{ + MLNVectorTileSourceOptionEncoding: [NSValue value:&mlt withObjCType:@encode(MLNVectorTileSourceEncoding)], + }); + + // the encoding is reflected by the mbgl tileset + XCTAssertEqual(tileSet.vectorEncoding, mbgl::Tileset::VectorEncoding::MLT); + XCTAssertFalse(tileSet.rasterEncoding); } - (void)testInvalidTileSet { diff --git a/platform/default/src/mbgl/storage/mbtiles_file_source.cpp b/platform/default/src/mbgl/storage/mbtiles_file_source.cpp index 0da19d84e..3556b181a 100644 --- a/platform/default/src/mbgl/storage/mbtiles_file_source.cpp +++ b/platform/default/src/mbgl/storage/mbtiles_file_source.cpp @@ -105,6 +105,11 @@ public: const auto format_ptr = values.find("format"); const std::string format = (format_ptr == values.end()) ? "png" : format_ptr->second; + // Translate MIME type field to source encoding. + if (format == "mlt" || format == "application/vnd.maplibre-vector-tile") { + doc.AddMember("encoding", "mlt", allocator); + } + if (format != "pbf" && !values.contains("scale")) { values["scale"] = "1"; } diff --git a/platform/default/src/mbgl/storage/pmtiles_file_source.cpp b/platform/default/src/mbgl/storage/pmtiles_file_source.cpp index 5f6da10f7..f15e119f8 100644 --- a/platform/default/src/mbgl/storage/pmtiles_file_source.cpp +++ b/platform/default/src/mbgl/storage/pmtiles_file_source.cpp @@ -47,6 +47,11 @@ std::string extract_url(const std::string& url) { } } // namespace +// temporary, remove this when it's available in `pmtiles.hpp` +namespace pmtiles { +const uint8_t TILETYPE_MLT = 0x6; +} // namespace pmtiles + namespace mbgl { using namespace rapidjson; @@ -305,6 +310,11 @@ private: rapidjson::Value().SetString(std::string(util::PMTILES_PROTOCOL + url), allocator), allocator); } + // Translate tile type field to source encoding. + if (header.tile_type == pmtiles::TILETYPE_MLT) { + doc.AddMember("encoding", "mlt", allocator); + } + if (!doc.HasMember("bounds")) { doc.AddMember("bounds", rapidjson::Value(), allocator); } diff --git a/render-test/render_test.cpp b/render-test/render_test.cpp index ea6c41685..b9e504e5a 100644 --- a/render-test/render_test.cpp +++ b/render-test/render_test.cpp @@ -131,6 +131,57 @@ ArgumentsTuple parseArguments(int argc, char** argv) { updateResults, std::move(testFilter)}; } + +void runWithAlternateSources(TestRunner& runner, TestMetadata& metadata, bool& errored, bool& passed) { + constexpr auto replacementsKey = "source-replace"; + constexpr auto targetKey = "replace"; + constexpr auto sourceKey = "with"; + constexpr auto sourcesKey = "sources"; + + if (!metadata.document.HasMember("metadata") || !metadata.document["metadata"].HasMember("test")) { + return; + } + + auto& testElement = metadata.document["metadata"]["test"]; + if (!testElement.HasMember(replacementsKey) || !testElement[replacementsKey].IsArray()) { + return; + } + + const auto& replacesElement = testElement[replacementsKey]; + if (!replacesElement.IsArray() || replacesElement.Empty()) { + return; + } + + auto& sources = metadata.document[sourcesKey]; + + // Each item in the source replacements array... + for (auto i = replacesElement.Begin(); i != replacesElement.End(); ++i) { + const auto& entry = *i; + if (entry.IsObject() && entry.HasMember(targetKey) && entry.HasMember(sourceKey) && + entry[targetKey].IsString() && entry[sourceKey].IsString()) { + const auto* targetName = entry[targetKey].GetString(); + const auto* sourceName = entry[sourceKey].GetString(); + if (sources.HasMember(targetName) && sources[targetName].IsObject() && sources.HasMember(sourceName) && + sources[sourceName].IsObject()) { + // Swap the named sources + sources[targetName].Swap(sources[sourceName]); + + // run the test again with the new source + runner.run(metadata); + + // Restore the original source + sources[targetName].Swap(sources[sourceName]); + + // stop if the test fails + errored = metadata.metricsErrored || metadata.renderErrored || metadata.labelCutOffFound; + passed = !errored && !metadata.metricsFailed && !metadata.renderFailed; + if (!passed) { + break; + } + } + } + } +} } // namespace namespace mbgl { @@ -200,7 +251,7 @@ int runRenderTests(int argc, char** argv, std::function testStatus) { if (it != ignores.end()) { metadata.ignoredTest = shouldIgnore = true; ignoreReason = it->second; - if (ignoreReason.rfind("skip", 0) == 0) { + if (ignoreReason.starts_with("skip")) { printf(ANSI_COLOR_GRAY "* skipped %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str()); mbgl::Log::Info(mbgl::Event::General, "* skipped " + id + "(" + ignoreReason + ")"); continue; @@ -217,6 +268,10 @@ int runRenderTests(int argc, char** argv, std::function testStatus) { bool errored = metadata.metricsErrored || metadata.renderErrored || metadata.labelCutOffFound; bool passed = !errored && !metadata.metricsFailed && !metadata.renderFailed; + if (passed) { + runWithAlternateSources(runner, metadata, errored, passed); + } + if (shouldIgnore) { if (passed) { status = "ignored passed"; diff --git a/src/mbgl/geometry/dem_data.cpp b/src/mbgl/geometry/dem_data.cpp index 81032006f..1bb6eb93c 100644 --- a/src/mbgl/geometry/dem_data.cpp +++ b/src/mbgl/geometry/dem_data.cpp @@ -3,7 +3,7 @@ namespace mbgl { -DEMData::DEMData(const PremultipliedImage& _image, Tileset::DEMEncoding _encoding) +DEMData::DEMData(const PremultipliedImage& _image, Tileset::RasterEncoding _encoding) : dim(_image.size.height), // extra two pixels per row for border backfilling on either edge stride(dim + 2), @@ -99,7 +99,7 @@ const std::array& DEMData::getUnpackVector() const { // https://aws.amazon.com/public-datasets/terrain/ static const std::array unpackTerrarium = {{256.0f, 1.0f, 1.0f / 256.0f, 32768.0f}}; - return encoding == Tileset::DEMEncoding::Terrarium ? unpackTerrarium : unpackMapbox; + return encoding == Tileset::RasterEncoding::Terrarium ? unpackTerrarium : unpackMapbox; } } // namespace mbgl diff --git a/src/mbgl/geometry/dem_data.hpp b/src/mbgl/geometry/dem_data.hpp index 81d21e45a..d63915d8a 100644 --- a/src/mbgl/geometry/dem_data.hpp +++ b/src/mbgl/geometry/dem_data.hpp @@ -13,7 +13,7 @@ namespace mbgl { class DEMData { public: - DEMData(const PremultipliedImage& image, Tileset::DEMEncoding encoding); + DEMData(const PremultipliedImage& image, Tileset::RasterEncoding encoding); void backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy); int32_t get(int32_t x, int32_t y) const; @@ -24,7 +24,7 @@ public: const int32_t dim; const int32_t stride; - const Tileset::DEMEncoding encoding; + const Tileset::RasterEncoding encoding; private: std::shared_ptr image; diff --git a/src/mbgl/gfx/fill_generator.cpp b/src/mbgl/gfx/fill_generator.cpp index 4e5f61f3b..4f4a627aa 100644 --- a/src/mbgl/gfx/fill_generator.cpp +++ b/src/mbgl/gfx/fill_generator.cpp @@ -54,10 +54,10 @@ std::size_t totalVerticesCheck(const GeometryCollection& polygon) { void addFillIndices(SegmentVector& fillSegments, gfx::IndexVector& fillIndexes, - std::vector& indices, - std::size_t startVertices, - std::size_t totalVertices) { - std::size_t nIndices = indices.size(); + const std::span& indices, + const std::size_t startVertices, + const std::size_t totalVertices) { + const std::size_t nIndices = indices.size(); assert(nIndices % 3 == 0); if (fillSegments.empty() || @@ -66,10 +66,13 @@ void addFillIndices(SegmentVector& fillSegments, } auto& triangleSegment = fillSegments.back(); - assert(triangleSegment.vertexLength <= std::numeric_limits::max()); + assert(triangleSegment.vertexLength + totalVertices <= std::numeric_limits::max()); const auto triangleIndex = static_cast(triangleSegment.vertexLength); for (std::size_t i = 0; i < nIndices; i += 3) { + assert( + std::max({triangleIndex + indices[i + 0], triangleIndex + indices[i + 1], triangleIndex + indices[i + 2]}) < + triangleIndex + totalVertices); fillIndexes.emplace_back( triangleIndex + indices[i], triangleIndex + indices[i + 1], triangleIndex + indices[i + 2]); } @@ -78,8 +81,8 @@ void addFillIndices(SegmentVector& fillSegments, triangleSegment.indexLength += nIndices; } -void addOutlineIndices(std::size_t base, - std::size_t nVertices, +void addOutlineIndices(const std::size_t base, + const std::size_t nVertices, SegmentVector& lineSegments, gfx::IndexVector& lineIndexes) { if (nVertices == 0) return; @@ -206,21 +209,36 @@ void generateFillAndOutineBuffers(const GeometryCollection& geometry, gfx::PolylineGeneratorOptions lineOptions; lineOptions.type = FeatureType::Polygon; + // If we have pre-tessellated geometry, multi-polygons are tessellated + // together, so we need to add them to the fill segment all at once. + if (!geometry.getTriangles().empty()) { + const std::size_t startVertices = fillVertices.elements(); + std::size_t totalVertices = 0; + for (const auto& polygon : geometry) { + totalVertices += polygon.size(); + addRingVertices(fillVertices, polygon); + } + addFillIndices(fillSegments, fillIndexes, geometry.getTriangles(), startVertices, totalVertices); + return; + } + for (auto& polygon : classifyRings(geometry)) { // Optimize polygons with many interior rings for earcut tesselation. limitHoles(polygon, 500); - std::size_t totalVertices = totalVerticesCheck(polygon); - std::size_t startVertices = fillVertices.elements(); + const std::size_t totalVertices = totalVerticesCheck(polygon); + const std::size_t startVertices = fillVertices.elements(); for (const auto& ring : polygon) { - std::size_t base = fillVertices.elements(); - std::size_t nVertices = addRingVertices(fillVertices, ring); + const std::size_t base = fillVertices.elements(); + const std::size_t nVertices = addRingVertices(fillVertices, ring); addOutlineIndices(base, nVertices, basicLineSegments, basicLineIndexes); lineGenerator.generate(ring, lineOptions); } + // tessellate, if no triangles are provided std::vector indices = mapbox::earcut(polygon); + addFillIndices(fillSegments, fillIndexes, indices, startVertices, totalVertices); } } diff --git a/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp b/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp index 26f806c5a..76b973531 100644 --- a/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp +++ b/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp @@ -11,13 +11,13 @@ namespace gfx { class HillshadePrepareDrawableData : public DrawableData { public: - HillshadePrepareDrawableData(int32_t stride_, Tileset::DEMEncoding encoding_, uint8_t maxzoom_) + HillshadePrepareDrawableData(int32_t stride_, Tileset::RasterEncoding encoding_, uint8_t maxzoom_) : stride(stride_), encoding(encoding_), maxzoom(maxzoom_) {} int32_t stride; - Tileset::DEMEncoding encoding; + Tileset::RasterEncoding encoding; uint8_t maxzoom; }; diff --git a/src/mbgl/programs/programs.cpp b/src/mbgl/programs/programs.cpp new file mode 100644 index 000000000..cedd07520 --- /dev/null +++ b/src/mbgl/programs/programs.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +Programs::Programs(const ProgramParameters& programParameters_) + : programParameters(programParameters_) {} + +Programs::~Programs() = default; + +namespace { +/// @brief Register a list of types with a shader registry instance +/// @tparam ...T Type list parameter pack +/// @param registry A shader registry instance +/// programParameters_ ProgramParameters used to initialize each instance +template +void registerTypes(gfx::ShaderRegistry& registry, const ProgramParameters& programParameters_) { + /// The following fold expression will create a shared_ptr for every type + /// in the parameter pack and register it with the shader registry. + + /// Registration calls are wrapped in a lambda that throws on registration + /// failure, we shouldn't expect registration to faill unless the shader + /// registry instance provided already has conflicting programs present. + ( + [](bool expr) { + if (!expr) { + throw std::runtime_error("Failed to register " + std::string(T::Name) + " with shader registry!"); + } + }(registry.getLegacyGroup().registerShader(std::make_shared(programParameters_))), + ...); +} +} // namespace + +void Programs::registerWith(gfx::ShaderRegistry& registry) { +#if MLN_LEGACY_RENDERER + /// The following types will be registered + registerTypes(registry, programParameters); +#else + /// The following types will be registered + registerTypes(registry, programParameters); +#endif +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.cpp b/src/mbgl/renderer/buckets/hillshade_bucket.cpp index 8a653c20b..a308fc0f4 100644 --- a/src/mbgl/renderer/buckets/hillshade_bucket.cpp +++ b/src/mbgl/renderer/buckets/hillshade_bucket.cpp @@ -6,7 +6,7 @@ namespace mbgl { using namespace style; -HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_, Tileset::DEMEncoding encoding) +HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_, Tileset::RasterEncoding encoding) : demdata(image_, encoding) {} HillshadeBucket::HillshadeBucket(DEMData&& demdata_) diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.hpp b/src/mbgl/renderer/buckets/hillshade_bucket.hpp index 9f3296ca9..eab5fa759 100644 --- a/src/mbgl/renderer/buckets/hillshade_bucket.hpp +++ b/src/mbgl/renderer/buckets/hillshade_bucket.hpp @@ -19,8 +19,8 @@ using HillshadeLayoutVertex = gfx::Vertex, Tileset::DEMEncoding encoding); + HillshadeBucket(PremultipliedImage&&, Tileset::RasterEncoding encoding); + HillshadeBucket(std::shared_ptr, Tileset::RasterEncoding encoding); HillshadeBucket(DEMData&&); ~HillshadeBucket() override; diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 6777c77a8..a754a8348 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -79,7 +79,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const std::size_t first = [&coordinates, &len] { std::size_t i = 0; // If the line has duplicate vertices at the start, adjust index to remove them. - while (i < len - 1 && coordinates[i] == coordinates[i + 1]) { + while (i + 1 < len && coordinates[i] == coordinates[i + 1]) { i++; } return i; @@ -102,17 +102,16 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, return; } - const auto& props = feature.getProperties(); - auto clip_start_it = props.find("mapbox_clip_start"); - auto clip_end_it = props.find("mapbox_clip_end"); - if (clip_start_it != props.end() && clip_end_it != props.end()) { + const auto clip_start = feature.getValue("mapbox_clip_start"); + const auto clip_end = feature.getValue("mapbox_clip_end"); + if (clip_start && clip_end) { double total_length = 0.0; for (std::size_t i = first; i < len - 1; ++i) { total_length += util::dist(coordinates[i], coordinates[i + 1]); } options.clipDistances = gfx::PolylineGeneratorDistances{ - *numericValue(clip_start_it->second), *numericValue(clip_end_it->second), total_length}; + *numericValue(*clip_start), *numericValue(*clip_end), total_length}; } options.joinType = layout.evaluate(zoom, feature, canonical); diff --git a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp index 24fa2452b..f62f464ff 100644 --- a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp @@ -22,8 +22,8 @@ constexpr std::array unpackMapbox = {{6553.6f, 25.6f, 0.1f, 10000.0f}} // https://aws.amazon.com/public-datasets/terrain/ constexpr std::array unpackTerrarium = {{256.0f, 1.0f, 1.0f / 256.0f, 32768.0f}}; -constexpr const std::array& getUnpackVector(const Tileset::DEMEncoding encoding) { - return (encoding == Tileset::DEMEncoding::Terrarium) ? unpackTerrarium : unpackMapbox; +constexpr const std::array& getUnpackVector(const Tileset::RasterEncoding encoding) { + return (encoding == Tileset::RasterEncoding::Terrarium) ? unpackTerrarium : unpackMapbox; } } // namespace diff --git a/src/mbgl/renderer/render_source.cpp b/src/mbgl/renderer/render_source.cpp index 7e2aa3011..70f01e534 100644 --- a/src/mbgl/renderer/render_source.cpp +++ b/src/mbgl/renderer/render_source.cpp @@ -24,6 +24,7 @@ std::unique_ptr RenderSource::create(const Immutable const TaggedScheduler& threadPool_) { switch (impl->type) { case SourceType::Vector: + // the TileSet isn't available yet, so we can't make different sources by format return std::make_unique(staticImmutableCast(impl), std::move(threadPool_)); case SourceType::Raster: diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp index 383de133a..3e90fd81a 100644 --- a/src/mbgl/renderer/sources/render_vector_source.cpp +++ b/src/mbgl/renderer/sources/render_vector_source.cpp @@ -1,8 +1,10 @@ #include + #include #include -#include #include +#include +#include namespace mbgl { @@ -20,17 +22,29 @@ void RenderVectorSource::updateInternal(const Tileset& tileset, const bool needsRendering, const bool needsRelayout, const TileParameters& parameters) { - tilePyramid.update(layers, - needsRendering, - needsRelayout, - parameters, - *baseImpl, - util::tileSize_I, - tileset.zoomRange, - tileset.bounds, - [&](const OverscaledTileID& tileID, TileObserver* observer_) { - return std::make_unique(tileID, baseImpl->id, parameters, tileset, observer_); - }); + tilePyramid.update( + layers, + needsRendering, + needsRelayout, + parameters, + *baseImpl, + util::tileSize_I, + tileset.zoomRange, + tileset.bounds, + [&](const OverscaledTileID& tileID, TileObserver* observer_) -> std::unique_ptr { + if (!isMLT.has_value()) { + auto impl = staticImmutableCast(baseImpl); + assert(impl->tileset); // we should have one by now + if (impl->tileset) { + isMLT = (impl->tileset->vectorEncoding == Tileset::VectorEncoding::MLT); + } + } + if (isMLT && *isMLT) { + return std::make_unique(tileID, baseImpl->id, parameters, tileset, observer_); + } else { + return std::make_unique(tileID, baseImpl->id, parameters, tileset, observer_); + } + }); } } // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_vector_source.hpp b/src/mbgl/renderer/sources/render_vector_source.hpp index aa3d7c122..602a2f9bb 100644 --- a/src/mbgl/renderer/sources/render_vector_source.hpp +++ b/src/mbgl/renderer/sources/render_vector_source.hpp @@ -17,6 +17,9 @@ private: bool needsRelayout, const TileParameters&) override; const std::optional& getTileset() const override; + +private: + std::optional isMLT; }; } // namespace mbgl diff --git a/src/mbgl/style/conversion/raster_dem_options.cpp b/src/mbgl/style/conversion/raster_dem_options.cpp deleted file mode 100644 index 29f50dffc..000000000 --- a/src/mbgl/style/conversion/raster_dem_options.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -#include - -namespace mbgl { -namespace style { -namespace conversion { - -std::optional Converter::operator()(const Convertible& value, Error& error) const { - RasterDEMOptions options; - - auto encodingValue = objectMember(value, "encoding"); - if (encodingValue) { - std::optional 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 diff --git a/src/mbgl/style/conversion/source.cpp b/src/mbgl/style/conversion/source.cpp index e04ff6d44..c7e0049ed 100644 --- a/src/mbgl/style/conversion/source.cpp +++ b/src/mbgl/style/conversion/source.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -16,8 +16,8 @@ namespace mbgl { namespace style { namespace conversion { -// A tile source can either specify a URL to TileJSON, or inline TileJSON. namespace { +// A tile source can either specify a URL to TileJSON, or inline TileJSON. std::optional> convertURLOrTileset(const Convertible& value, Error& error) { auto urlVal = objectMember(value, "url"); if (!urlVal) { @@ -25,7 +25,7 @@ std::optional> convertURLOrTileset(const Convertib if (!tileset) { return std::nullopt; } - return {*tileset}; + return {std::move(*tileset)}; } std::optional url = toString(*urlVal); @@ -34,7 +34,7 @@ std::optional> convertURLOrTileset(const Convertib return std::nullopt; } - return {*url}; + return {std::move(*url)}; } std::optional> convertRasterSource(const std::string& id, @@ -83,7 +83,7 @@ std::optional> convertRasterDEMSource(const std::string& 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 options = convert(value, error); + auto options = convert(value, error); return {std::make_unique(id, std::move(*urlOrTileset), tileSize, options)}; } @@ -91,11 +91,11 @@ std::optional> convertRasterDEMSource(const std::string& std::optional> convertVectorSource(const std::string& id, const Convertible& value, Error& error) { - std::optional> urlOrTileset = convertURLOrTileset(value, error); + auto urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return std::nullopt; } - auto maxzoomValue = objectMember(value, "maxzoom"); + const auto maxzoomValue = objectMember(value, "maxzoom"); std::optional maxzoom; if (maxzoomValue) { maxzoom = toNumber(*maxzoomValue); @@ -104,7 +104,7 @@ std::optional> convertVectorSource(const std::string& id return std::nullopt; } } - auto minzoomValue = objectMember(value, "minzoom"); + const auto minzoomValue = objectMember(value, "minzoom"); std::optional minzoom; if (minzoomValue) { minzoom = toNumber(*minzoomValue); @@ -113,7 +113,20 @@ std::optional> convertVectorSource(const std::string& id return std::nullopt; } } - return {std::make_unique(id, std::move(*urlOrTileset), std::move(maxzoom), std::move(minzoom))}; + const auto encodingValue = objectMember(value, "encoding"); + auto encoding = Tileset::VectorEncoding::Mapbox; + if (encodingValue) { + const auto encodingStr = toString(*encodingValue); + if (encodingStr && encodingStr == "mvt") { + encoding = Tileset::VectorEncoding::Mapbox; + } else if (encodingStr && encodingStr == "mlt") { + encoding = Tileset::VectorEncoding::MLT; + } else { + error.message = "invalid encoding"; + return std::nullopt; + } + } + return {std::make_unique(id, std::move(*urlOrTileset), maxzoom, minzoom, encoding)}; } std::optional> convertGeoJSONSource(const std::string& id, diff --git a/src/mbgl/style/conversion/source_options.cpp b/src/mbgl/style/conversion/source_options.cpp new file mode 100644 index 000000000..b1dd31e62 --- /dev/null +++ b/src/mbgl/style/conversion/source_options.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +std::optional Converter::operator()(const Convertible& value, Error& error) const { + const auto encodingValue = objectMember(value, "encoding"); + if (encodingValue) { + const auto encoding = toString(*encodingValue); + if (encoding && *encoding == "terrarium") { + return {{.rasterEncoding = Tileset::RasterEncoding::Terrarium}}; + } else if (encoding && *encoding == "mapbox") { + return {{.rasterEncoding = Tileset::RasterEncoding::Mapbox}}; + } else if (encoding && *encoding == "mvt") { + return {{.vectorEncoding = Tileset::VectorEncoding::Mapbox}}; + } else if (encoding && *encoding == "mlt") { + return {{.vectorEncoding = Tileset::VectorEncoding::MLT}}; + } else { + error.message = + "invalid encoding - valid types are 'mapbox' and 'terrarium' for raster sources, 'mvt' and 'mlt' for " + "vector sources"; + return std::nullopt; + } + } + return {}; +} + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/conversion/tileset.cpp b/src/mbgl/style/conversion/tileset.cpp index c18a83339..a942a7528 100644 --- a/src/mbgl/style/conversion/tileset.cpp +++ b/src/mbgl/style/conversion/tileset.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -39,10 +39,13 @@ std::optional Converter::operator()(const Convertible& value, } } - auto rasterDEMOptions = convert(value, error); - if (rasterDEMOptions) { - if (std::optional encoding = rasterDEMOptions.value().encoding) { - result.encoding = encoding.value(); + auto options = convert(value, error); + if (options) { + if (const auto encoding = options->rasterEncoding) { + result.rasterEncoding = encoding; + } + if (const auto encoding = options->vectorEncoding) { + result.vectorEncoding = encoding; } } diff --git a/src/mbgl/style/sources/raster_dem_source.cpp b/src/mbgl/style/sources/raster_dem_source.cpp index 7782e7a56..b62b2f1c2 100644 --- a/src/mbgl/style/sources/raster_dem_source.cpp +++ b/src/mbgl/style/sources/raster_dem_source.cpp @@ -15,7 +15,7 @@ namespace style { RasterDEMSource::RasterDEMSource(std::string id, variant urlOrTileset_, uint16_t tileSize, - std::optional options_) + std::optional options_) : RasterSource(std::move(id), std::move(urlOrTileset_), tileSize, SourceType::RasterDEM), options(std::move(options_)) {} @@ -30,8 +30,8 @@ bool RasterDEMSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) void RasterDEMSource::setTilesetOverrides(Tileset& tileset) { if (options) { - if (std::optional encoding = options.value().encoding) { - tileset.encoding = encoding.value(); + if (const auto encoding = options->rasterEncoding) { + tileset.rasterEncoding = encoding; } } } diff --git a/src/mbgl/style/sources/vector_source.cpp b/src/mbgl/style/sources/vector_source.cpp index bd61f5ed2..d65d6b887 100644 --- a/src/mbgl/style/sources/vector_source.cpp +++ b/src/mbgl/style/sources/vector_source.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace mbgl { namespace style { @@ -17,10 +18,12 @@ namespace style { VectorSource::VectorSource(std::string id, variant urlOrTileset_, std::optional maxZoom_, - std::optional minZoom_) + std::optional minZoom_, + Tileset::VectorEncoding encoding_) : TileSource(id, urlOrTileset_, util::tileSize_I, SourceType::Vector), maxZoom(std::move(maxZoom_)), - minZoom(std::move(minZoom_)) {} + minZoom(std::move(minZoom_)), + encoding(encoding_) {} void VectorSource::setTilesetOverrides(Tileset& tileset) { if (maxZoom) { diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp index 993c709fb..b8f395f4c 100644 --- a/src/mbgl/tile/geometry_tile_data.hpp +++ b/src/mbgl/tile/geometry_tile_data.hpp @@ -4,11 +4,14 @@ #include #include +#include +#include #include #include -#include -#include +namespace mlt { +class MapLibreTile; +} namespace mbgl { class CanonicalTileID; @@ -44,8 +47,17 @@ public: GeometryCollection clone() const { return GeometryCollection(*this); } + const auto& getTriangles() const { return triangles; } + void setTriangles(std::shared_ptr owner, std::span triangles_) { + triangleOwner = std::move(owner); + triangles = triangles_; + } + private: GeometryCollection(const GeometryCollection&) = default; + + std::shared_ptr triangleOwner; + std::span triangles = {}; }; class GeometryTileFeature { diff --git a/src/mbgl/tile/raster_dem_tile.cpp b/src/mbgl/tile/raster_dem_tile.cpp index 94c1e7a76..4e6ac3b87 100644 --- a/src/mbgl/tile/raster_dem_tile.cpp +++ b/src/mbgl/tile/raster_dem_tile.cpp @@ -24,7 +24,7 @@ RasterDEMTile::RasterDEMTile(const OverscaledTileID& id_, threadPool(parameters.threadPool), mailbox(std::make_shared(*Scheduler::GetCurrent())), worker(parameters.threadPool, ActorRef(*this, mailbox)) { - encoding = tileset.encoding; + encoding = tileset.rasterEncoding.value_or(Tileset::RasterEncoding::Mapbox); if (id.canonical.y == 0) { // this tile doesn't have upper neighboring tiles so marked those as backfilled neighboringTiles = neighboringTiles | DEMTileNeighbors::NoUpper; diff --git a/src/mbgl/tile/raster_dem_tile.hpp b/src/mbgl/tile/raster_dem_tile.hpp index afcdef74a..7594afdd3 100644 --- a/src/mbgl/tile/raster_dem_tile.hpp +++ b/src/mbgl/tile/raster_dem_tile.hpp @@ -99,7 +99,7 @@ private: Actor worker; uint64_t correlationID = 0; - Tileset::DEMEncoding encoding; + Tileset::RasterEncoding encoding; // Contains the Bucket object for the tile. Buckets are render // objects and they get added by tile parsing operations. diff --git a/src/mbgl/tile/raster_dem_tile_worker.cpp b/src/mbgl/tile/raster_dem_tile_worker.cpp index 3b24e3538..4da74bfb2 100644 --- a/src/mbgl/tile/raster_dem_tile_worker.cpp +++ b/src/mbgl/tile/raster_dem_tile_worker.cpp @@ -11,7 +11,7 @@ RasterDEMTileWorker::RasterDEMTileWorker(const ActorRef&, A void RasterDEMTileWorker::parse(const std::shared_ptr& data, uint64_t correlationID, - Tileset::DEMEncoding encoding) { + Tileset::RasterEncoding encoding) { if (!data) { parent.invoke(&RasterDEMTile::onParsed, nullptr, correlationID); // No data; empty tile. diff --git a/src/mbgl/tile/raster_dem_tile_worker.hpp b/src/mbgl/tile/raster_dem_tile_worker.hpp index cce569c41..fcb210808 100644 --- a/src/mbgl/tile/raster_dem_tile_worker.hpp +++ b/src/mbgl/tile/raster_dem_tile_worker.hpp @@ -14,7 +14,9 @@ class RasterDEMTileWorker { public: RasterDEMTileWorker(const ActorRef&, ActorRef); - void parse(const std::shared_ptr& data, uint64_t correlationID, Tileset::DEMEncoding encoding); + void parse(const std::shared_ptr& data, + uint64_t correlationID, + Tileset::RasterEncoding encoding); private: ActorRef parent; diff --git a/src/mbgl/tile/vector_mlt_tile.cpp b/src/mbgl/tile/vector_mlt_tile.cpp new file mode 100644 index 000000000..60ffd8ec6 --- /dev/null +++ b/src/mbgl/tile/vector_mlt_tile.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include +#include + +#include + +namespace mbgl { + +VectorMLTTile::VectorMLTTile(const OverscaledTileID& id_, + std::string sourceID_, + const TileParameters& parameters_, + const Tileset& tileset_, + TileObserver* observer_) + : VectorTile(id_, std::move(sourceID_), parameters_, tileset_, observer_) {} + +void VectorMLTTile::setData(const std::shared_ptr& data_) { + if (!obsolete) { + GeometryTile::setData(data_ ? std::make_unique(data_) : nullptr); + } +} + +} // namespace mbgl diff --git a/src/mbgl/tile/vector_mlt_tile.hpp b/src/mbgl/tile/vector_mlt_tile.hpp new file mode 100644 index 000000000..cd3f4b88b --- /dev/null +++ b/src/mbgl/tile/vector_mlt_tile.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class Tileset; +class TileParameters; + +class VectorMLTTile : public VectorTile { +public: + VectorMLTTile(const OverscaledTileID&, + std::string sourceID, + const TileParameters&, + const Tileset&, + TileObserver* observer = nullptr); + + void setData(const std::shared_ptr& data) override; +}; + +} // namespace mbgl diff --git a/src/mbgl/tile/vector_mlt_tile_data.cpp b/src/mbgl/tile/vector_mlt_tile_data.cpp new file mode 100644 index 000000000..bbab4cb13 --- /dev/null +++ b/src/mbgl/tile/vector_mlt_tile_data.cpp @@ -0,0 +1,220 @@ +#include +#include + +#include +#include +#include + +#include +#include + +namespace mbgl { + +using GeometryType = mlt::metadata::tileset::GeometryType; + +VectorMLTTileFeature::VectorMLTTileFeature(std::shared_ptr tile_, + const mlt::Layer& layer_, + const mlt::Feature& feature_, + std::uint32_t extent_) + : tile(std::move(tile_)), + layer(layer_), + feature(feature_), + extent(extent_) {} + +FeatureType VectorMLTTileFeature::getType() const { + switch (feature.getGeometry().type) { + case GeometryType::POINT: + return FeatureType::Point; + case GeometryType::MULTIPOINT: + case GeometryType::MULTILINESTRING: + case GeometryType::LINESTRING: + return FeatureType::LineString; + case GeometryType::POLYGON: + case GeometryType::MULTIPOLYGON: + return FeatureType::Polygon; + default: + return FeatureType::Unknown; + } +} + +namespace { +struct PropertyVisitor { + Value operator()(std::nullptr_t) const { return mapbox::feature::null_value; } + Value operator()(bool value) const { return value; } + Value operator()(std::uint32_t value) const { return value; } + Value operator()(std::uint64_t value) const { return value; } + Value operator()(float value) const { return value; } + Value operator()(double value) const { return value; } + Value operator()(std::string_view value) const { return std::string(value); } + + template + Value operator()(std::optional value) const { + return value ? operator()(*value) : NullValue(); + } +}; +} // namespace + +std::optional VectorMLTTileFeature::getValue(const std::string& key) const { + if (auto prop = feature.getProperty(key, layer)) { + return std::visit(PropertyVisitor(), *prop); + } + return std::nullopt; +} + +const PropertyMap& VectorMLTTileFeature::getProperties() const { + if (!properties) { + const PropertyVisitor visitor; + properties.emplace(); + properties->reserve(layer.getProperties().size()); + for (const auto& [key, props] : layer.getProperties()) { + auto value = props.getProperty(feature.getIndex()); + auto prop = value ? std::visit(visitor, std::move(*value)) : mapbox::feature::null_value; + properties->emplace(key, std::move(prop)); + } + } + return *properties; +} + +FeatureIdentifier VectorMLTTileFeature::getID() const { + return feature.getID(); +} + +namespace { +struct PointConverter { + double scale; + inline constexpr static GeometryCoordinate convert(double scale, const mlt::Coordinate& coord) { + return {static_cast(std::round(coord.x * scale)), + static_cast(std::round(coord.y * scale))}; + } + GeometryCoordinate operator()(const mlt::Coordinate& coord) const { return convert(scale, coord); } + GeometryCoordinates operator()(const mlt::CoordVec& coords) const { + GeometryCoordinates result(coords.size()); + std::ranges::transform(coords, result.begin(), *this); + return result; + } +}; +} // namespace + +const GeometryCollection& VectorMLTTileFeature::getGeometries() const { + MLN_TRACE_FUNC(); + + if (!lines) { + const auto scale = static_cast(util::EXTENT) / extent; + const auto& geometry = feature.getGeometry(); + const PointConverter convert{scale}; + switch (geometry.type) { + case GeometryType::POINT: { + const auto& geom = static_cast(geometry); + lines = GeometryCollection{{convert(geom.getCoordinate())}}; + break; + } + case GeometryType::MULTIPOINT: + case GeometryType::LINESTRING: { + const auto& geom = static_cast(geometry); + lines = GeometryCollection{convert(geom.getCoordinates())}; + break; + } + case GeometryType::POLYGON: { + const auto& geom = static_cast(geometry); + lines.emplace(geom.getRings().size()); + std::ranges::transform(geom.getRings(), lines->begin(), convert); + if (!geometry.getTriangles().empty()) { + lines->setTriangles(tile, geometry.getTriangles()); + } + break; + } + case GeometryType::MULTILINESTRING: { + const auto& geom = static_cast(geometry); + lines.emplace(geom.getLineStrings().size()); + std::ranges::transform(geom.getLineStrings(), lines->begin(), convert); + break; + } + case GeometryType::MULTIPOLYGON: { + const auto& geom = static_cast(geometry); + const auto& polygons = geom.getPolygons(); + using RingVec = mlt::geometry::MultiPolygon::RingVec; + lines.emplace(std::accumulate( + polygons.begin(), polygons.end(), static_cast(0), [](std::size_t a, const RingVec& b) { + return a + b.size(); + })); + for (const auto& poly : polygons) { + std::ranges::transform(poly, std::back_inserter(*lines), convert); + } + if (!geometry.getTriangles().empty()) { + lines->setTriangles(tile, geometry.getTriangles()); + } + break; + } + default: + lines.emplace(); + break; + } + } + return *lines; +} + +VectorMLTTileLayer::VectorMLTTileLayer(std::shared_ptr tile_, const mlt::Layer& layer_) + : tile(std::move(tile_)), + layer(layer_) {} + +std::size_t VectorMLTTileLayer::featureCount() const { + return layer.getFeatures().size(); +} + +std::unique_ptr VectorMLTTileLayer::getFeature(std::size_t index) const { + const auto& features = layer.getFeatures(); + const mlt::Feature* targetFeature = nullptr; + targetFeature = &features[index]; + return std::make_unique(tile, layer, *targetFeature, layer.getExtent()); +} + +std::string VectorMLTTileLayer::getName() const { + return layer.getName(); +} + +VectorMLTTileData::VectorMLTTileData(std::shared_ptr data_) + : data(std::move(data_)) {} + +VectorMLTTileData::VectorMLTTileData(const VectorMLTTileData& other) + : data(other.data), + tile(other.tile) {} + +std::unique_ptr VectorMLTTileData::clone() const { + return std::make_unique(*this); +} + +std::unique_ptr VectorMLTTileData::getLayer(const std::string& name) const { + MLN_TRACE_FUNC(); + + if (data && !tile) { + try { + mlt::DataView tileData{data->data(), data->size()}; + tile = std::make_shared(mlt::Decoder().decode(tileData)); + } catch (const std::exception& ex) { + Log::Warning(Event::ParseTile, "MLT parse failed: " + std::string(ex.what())); + } + // We don't need the raw data anymore + data.reset(); + } + + if (tile) { + if (const auto* layer = tile->getLayer(name)) { + return std::make_unique(tile, *layer); + } + } + return nullptr; +} + +std::vector VectorMLTTileData::layerNames() const { + if (data && !data->empty() && !tile) { + getLayer({}); + } + if (tile) { + std::vector result(tile->getLayers().size()); + std::ranges::transform(tile->getLayers(), result.begin(), [](const auto& layer) { return layer.getName(); }); + return result; + } + return {}; +} + +} // namespace mbgl diff --git a/src/mbgl/tile/vector_mlt_tile_data.hpp b/src/mbgl/tile/vector_mlt_tile_data.hpp new file mode 100644 index 000000000..5a7830250 --- /dev/null +++ b/src/mbgl/tile/vector_mlt_tile_data.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include +#include + +#include +#include +#include + +namespace mlt { +class MapLibreTile; +class Feature; +class Layer; +} // namespace mlt + +namespace mbgl { +using MapLibreTile = mlt::MapLibreTile; + +class VectorMLTTileFeature : public GeometryTileFeature { +public: + VectorMLTTileFeature(std::shared_ptr, + const mlt::Layer& layer_, + const mlt::Feature&, + std::uint32_t extent); + VectorMLTTileFeature(const VectorMLTTileFeature&) = delete; + VectorMLTTileFeature(VectorMLTTileFeature&& other) + : tile(std::move(other.tile)), + layer(other.layer), + feature(other.feature), + extent(other.extent), + version(other.version), + lines(std::move(other.lines)), + properties(std::move(other.properties)) {} + + VectorMLTTileFeature& operator=(VectorMLTTileFeature&&) = delete; + VectorMLTTileFeature& operator=(const VectorMLTTileFeature&) = delete; + + FeatureType getType() const override; + std::optional getValue(const std::string& key) const override; + const PropertyMap& getProperties() const override; + FeatureIdentifier getID() const override; + const GeometryCollection& getGeometries() const override; + +private: + std::shared_ptr tile; + const mlt::Layer& layer; + mlt::Feature const& feature; + std::uint32_t extent; + int version; + + // lazy init + mutable std::optional lines; + mutable std::optional properties; +}; + +class VectorMLTTileLayer : public GeometryTileLayer { +public: + VectorMLTTileLayer(std::shared_ptr, const mlt::Layer&); + + std::size_t featureCount() const override; + std::unique_ptr getFeature(std::size_t i) const override; + std::string getName() const override; + +private: + const std::shared_ptr tile; + const mlt::Layer& layer; +}; + +class VectorMLTTileData : public GeometryTileData { +public: + VectorMLTTileData(std::shared_ptr data); + VectorMLTTileData(const VectorMLTTileData&); + VectorMLTTileData(VectorMLTTileData&&) = default; + + std::unique_ptr clone() const override; + std::unique_ptr getLayer(const std::string& name) const override; + + std::vector layerNames() const; + +private: + mutable std::shared_ptr data; + mutable std::shared_ptr tile; +}; + +} // namespace mbgl diff --git a/src/mbgl/tile/vector_mvt_tile.cpp b/src/mbgl/tile/vector_mvt_tile.cpp new file mode 100644 index 000000000..b93743bfd --- /dev/null +++ b/src/mbgl/tile/vector_mvt_tile.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include +#include + +#include + +namespace mbgl { + +VectorMVTTile::VectorMVTTile(const OverscaledTileID& id_, + std::string sourceID_, + const TileParameters& parameters_, + const Tileset& tileset_, + TileObserver* observer_) + : VectorTile(id_, std::move(sourceID_), parameters_, tileset_, observer_) {} + +void VectorMVTTile::setData(const std::shared_ptr& data_) { + if (!obsolete) { + GeometryTile::setData(data_ ? std::make_unique(data_) : nullptr); + } +} + +} // namespace mbgl diff --git a/src/mbgl/tile/vector_mvt_tile.hpp b/src/mbgl/tile/vector_mvt_tile.hpp new file mode 100644 index 000000000..716ba7fcc --- /dev/null +++ b/src/mbgl/tile/vector_mvt_tile.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class Tileset; +class TileParameters; + +class VectorMVTTile : public VectorTile { +public: + VectorMVTTile(const OverscaledTileID&, + std::string sourceID, + const TileParameters&, + const Tileset&, + TileObserver* observer = nullptr); + + void setData(const std::shared_ptr& data) override; +}; + +} // namespace mbgl diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_mvt_tile_data.cpp similarity index 56% rename from src/mbgl/tile/vector_tile_data.cpp rename to src/mbgl/tile/vector_mvt_tile_data.cpp index 644225a92..4a11a0231 100644 --- a/src/mbgl/tile/vector_tile_data.cpp +++ b/src/mbgl/tile/vector_mvt_tile_data.cpp @@ -1,14 +1,19 @@ -#include +#include + #include #include #include +#if ANDROID +#include +#endif + namespace mbgl { -VectorTileFeature::VectorTileFeature(const mapbox::vector_tile::layer& layer, const protozero::data_view& view) +VectorMVTTileFeature::VectorMVTTileFeature(const mapbox::vector_tile::layer& layer, const protozero::data_view& view) : feature(view, layer) {} -FeatureType VectorTileFeature::getType() const { +FeatureType VectorMVTTileFeature::getType() const { switch (feature.getType()) { case mapbox::vector_tile::GeomType::POINT: return FeatureType::Point; @@ -21,23 +26,23 @@ FeatureType VectorTileFeature::getType() const { } } -std::optional VectorTileFeature::getValue(const std::string& key) const { - const std::optional value(feature.getValue(key)); - return value->is() ? std::nullopt : value; +std::optional VectorMVTTileFeature::getValue(const std::string& key) const { + const auto value = feature.getValue(key); + return value.is() ? std::nullopt : std::optional{std::move(value)}; } -const PropertyMap& VectorTileFeature::getProperties() const { +const PropertyMap& VectorMVTTileFeature::getProperties() const { if (!properties) { properties = feature.getProperties(); } return *properties; } -FeatureIdentifier VectorTileFeature::getID() const { +FeatureIdentifier VectorMVTTileFeature::getID() const { return feature.getID(); } -const GeometryCollection& VectorTileFeature::getGeometries() const { +const GeometryCollection& VectorMVTTileFeature::getGeometries() const { MLN_TRACE_FUNC(); if (!lines) { @@ -57,30 +62,30 @@ const GeometryCollection& VectorTileFeature::getGeometries() const { return *lines; } -VectorTileLayer::VectorTileLayer(std::shared_ptr data_, const protozero::data_view& view) +VectorMVTTileLayer::VectorMVTTileLayer(std::shared_ptr data_, const protozero::data_view& view) : data(std::move(data_)), layer(view) {} -std::size_t VectorTileLayer::featureCount() const { +std::size_t VectorMVTTileLayer::featureCount() const { return layer.featureCount(); } -std::unique_ptr VectorTileLayer::getFeature(std::size_t i) const { - return std::make_unique(layer, layer.getFeature(i)); +std::unique_ptr VectorMVTTileLayer::getFeature(std::size_t i) const { + return std::make_unique(layer, layer.getFeature(i)); } -std::string VectorTileLayer::getName() const { +std::string VectorMVTTileLayer::getName() const { return layer.getName(); } -VectorTileData::VectorTileData(std::shared_ptr data_) +VectorMVTTileData::VectorMVTTileData(std::shared_ptr data_) : data(std::move(data_)) {} -std::unique_ptr VectorTileData::clone() const { - return std::make_unique(data); +std::unique_ptr VectorMVTTileData::clone() const { + return std::make_unique(data); } -std::unique_ptr VectorTileData::getLayer(const std::string& name) const { +std::unique_ptr VectorMVTTileData::getLayer(const std::string& name) const { MLN_TRACE_FUNC(); if (!parsed) { @@ -93,12 +98,12 @@ std::unique_ptr VectorTileData::getLayer(const std::string& n auto it = layers.find(name); if (it != layers.end()) { - return std::make_unique(data, it->second); + return std::make_unique(data, it->second); } return nullptr; } -std::vector VectorTileData::layerNames() const { +std::vector VectorMVTTileData::layerNames() const { return mapbox::vector_tile::buffer(*data).layerNames(); } diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_mvt_tile_data.hpp similarity index 78% rename from src/mbgl/tile/vector_tile_data.hpp rename to src/mbgl/tile/vector_mvt_tile_data.hpp index 472c9a6e6..09b1bbcf5 100644 --- a/src/mbgl/tile/vector_tile_data.hpp +++ b/src/mbgl/tile/vector_mvt_tile_data.hpp @@ -20,9 +20,9 @@ namespace mbgl { -class VectorTileFeature : public GeometryTileFeature { +class VectorMVTTileFeature : public GeometryTileFeature { public: - VectorTileFeature(const mapbox::vector_tile::layer&, const protozero::data_view&); + VectorMVTTileFeature(const mapbox::vector_tile::layer&, const protozero::data_view&); FeatureType getType() const override; std::optional getValue(const std::string& key) const override; @@ -36,9 +36,9 @@ private: mutable std::optional properties; }; -class VectorTileLayer : public GeometryTileLayer { +class VectorMVTTileLayer : public GeometryTileLayer { public: - VectorTileLayer(std::shared_ptr data, const protozero::data_view&); + VectorMVTTileLayer(std::shared_ptr data, const protozero::data_view&); std::size_t featureCount() const override; std::unique_ptr getFeature(std::size_t i) const override; @@ -49,9 +49,9 @@ private: mapbox::vector_tile::layer layer; }; -class VectorTileData : public GeometryTileData { +class VectorMVTTileData : public GeometryTileData { public: - VectorTileData(std::shared_ptr data); + VectorMVTTileData(std::shared_ptr data); std::unique_ptr clone() const override; std::unique_ptr getLayer(const std::string& name) const override; diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp index f39559d38..01c5d5ba4 100644 --- a/src/mbgl/tile/vector_tile.cpp +++ b/src/mbgl/tile/vector_tile.cpp @@ -1,18 +1,19 @@ +#include + #include #include -#include -#include + #include namespace mbgl { VectorTile::VectorTile(const OverscaledTileID& id_, std::string sourceID_, - const TileParameters& parameters, + const TileParameters& parameters_, const Tileset& tileset, TileObserver* observer_) - : GeometryTile(id_, std::move(sourceID_), parameters, observer_), - loader(*this, id_, parameters, tileset) {} + : GeometryTile(id_, std::move(sourceID_), parameters_, observer_), + loader(*this, id_, parameters_, tileset) {} VectorTile::~VectorTile() { // Don't rely on `~TileLoader` to close, it's not safe to call there. @@ -33,12 +34,4 @@ void VectorTile::setMetadata(std::optional modified_, std::optional& data_) { - if (obsolete) { - return; - } - - GeometryTile::setData(data_ ? std::make_unique(data_) : nullptr); -} - } // namespace mbgl diff --git a/src/mbgl/tile/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp index ab8f96281..0364c52c8 100644 --- a/src/mbgl/tile/vector_tile.hpp +++ b/src/mbgl/tile/vector_tile.hpp @@ -20,7 +20,8 @@ public: void setNecessity(TileNecessity) final; void setUpdateParameters(const TileUpdateParameters&) final; void setMetadata(std::optional modified, std::optional expires); - void setData(const std::shared_ptr& data); + + virtual void setData(const std::shared_ptr&) = 0; private: TileLoader loader; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0517fbdd6..e1a882d60 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,7 +52,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/source_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 diff --git a/test/geometry/dem_data.test.cpp b/test/geometry/dem_data.test.cpp index bb3e4049b..2899db830 100644 --- a/test/geometry/dem_data.test.cpp +++ b/test/geometry/dem_data.test.cpp @@ -17,7 +17,7 @@ auto fakeImage = [](Size s) { TEST(DEMData, ConstructorMapbox) { PremultipliedImage image = fakeImage({16, 16}); - DEMData demdata(image, Tileset::DEMEncoding::Mapbox); + DEMData demdata(image, Tileset::RasterEncoding::Mapbox); EXPECT_EQ(demdata.dim, 16); EXPECT_EQ(demdata.stride, 18); @@ -26,7 +26,7 @@ TEST(DEMData, ConstructorMapbox) { TEST(DEMData, ConstructorTerrarium) { PremultipliedImage image = fakeImage({16, 16}); - DEMData demdata(image, Tileset::DEMEncoding::Terrarium); + DEMData demdata(image, Tileset::RasterEncoding::Terrarium); EXPECT_EQ(demdata.dim, 16); EXPECT_EQ(demdata.stride, 18); @@ -35,7 +35,7 @@ TEST(DEMData, ConstructorTerrarium) { TEST(DEMData, InitialBackfill) { PremultipliedImage image1 = fakeImage({4, 4}); - DEMData dem1(image1, Tileset::DEMEncoding::Mapbox); + DEMData dem1(image1, Tileset::RasterEncoding::Mapbox); bool nonempty = true; // checking that a 1 px border around the fake image has been populated @@ -89,10 +89,10 @@ TEST(DEMData, InitialBackfill) { TEST(DEMData, BackfillNeighbor) { PremultipliedImage image1 = fakeImage({4, 4}); - DEMData dem0(image1, Tileset::DEMEncoding::Mapbox); + DEMData dem0(image1, Tileset::RasterEncoding::Mapbox); PremultipliedImage image2 = fakeImage({4, 4}); - DEMData dem1(image2, Tileset::DEMEncoding::Mapbox); + DEMData dem1(image2, Tileset::RasterEncoding::Mapbox); dem0.backfillBorder(dem1, -1, 0); for (int y = 0; y < 4; y++) { diff --git a/test/style/conversion/raster_dem_options.test.cpp b/test/style/conversion/raster_dem_options.test.cpp deleted file mode 100644 index 416bd3f27..000000000 --- a/test/style/conversion/raster_dem_options.test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -#include -#include -#include - -#include - -using namespace mbgl; -using namespace mbgl::style; -using namespace mbgl::style::conversion; - -TEST(RasterDEMOptions, Basic) { - Error error; - std::optional converted = convertJSON("{}", error); - ASSERT_TRUE((bool)converted); -} - -TEST(RasterDEMOptions, ErrorHandling) { - Error error; - std::optional converted = convertJSON( - 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 converted = convertJSON( - R"JSON({ - "encoding": "terrarium" - })JSON", - error); - ASSERT_EQ(converted.value().encoding, Tileset::DEMEncoding::Terrarium); -} - -TEST(RasterDEMOptions, MapboxEncodingParsed) { - Error error; - std::optional converted = convertJSON( - R"JSON({ - "encoding": "mapbox" - })JSON", - error); - ASSERT_EQ(converted.value().encoding, Tileset::DEMEncoding::Mapbox); -} diff --git a/test/style/conversion/source_options.test.cpp b/test/style/conversion/source_options.test.cpp new file mode 100644 index 000000000..cb5474d51 --- /dev/null +++ b/test/style/conversion/source_options.test.cpp @@ -0,0 +1,72 @@ +#include + +#include +#include +#include + +#include + +using namespace mbgl; +using namespace mbgl::style; +using namespace mbgl::style::conversion; + +TEST(SourceOptions, Basic) { + Error error; + auto converted = convertJSON("{}", error); + ASSERT_FALSE(converted); +} + +TEST(SourceOptions, ErrorHandling) { + Error error; + auto converted = convertJSON( + R"JSON({ + "encoding": "this isn't a valid encoding" + })JSON", + error); + ASSERT_FALSE(converted); + ASSERT_EQ(0, error.message.find("invalid encoding")); +} + +TEST(SourceOptions, TerrariumEncodingParsed) { + Error error; + auto converted = convertJSON( + R"JSON({ + "encoding": "terrarium" + })JSON", + error); + ASSERT_EQ(converted.value().rasterEncoding, Tileset::RasterEncoding::Terrarium); + ASSERT_FALSE(converted.value().vectorEncoding); +} + +TEST(SourceOptions, MapboxEncodingParsed) { + Error error; + auto converted = convertJSON( + R"JSON({ + "encoding": "mapbox" + })JSON", + error); + ASSERT_EQ(converted.value().rasterEncoding, Tileset::RasterEncoding::Mapbox); + ASSERT_FALSE(converted.value().vectorEncoding); +} + +TEST(SourceOptions, MVTEncodingParsed) { + Error error; + auto converted = convertJSON( + R"JSON({ + "encoding": "mvt" + })JSON", + error); + ASSERT_EQ(converted.value().vectorEncoding, Tileset::VectorEncoding::Mapbox); + ASSERT_FALSE(converted.value().rasterEncoding); +} + +TEST(SourceOptions, MLTEncodingParsed) { + Error error; + auto converted = convertJSON( + R"JSON({ + "encoding": "mlt" + })JSON", + error); + ASSERT_EQ(converted.value().vectorEncoding, Tileset::VectorEncoding::MLT); + ASSERT_FALSE(converted.value().rasterEncoding); +} diff --git a/test/tile/raster_dem_tile.test.cpp b/test/tile/raster_dem_tile.test.cpp index 2519eac70..60b4d12cd 100644 --- a/test/tile/raster_dem_tile.test.cpp +++ b/test/tile/raster_dem_tile.test.cpp @@ -66,7 +66,7 @@ TEST(RasterDEMTile, onError) { TEST(RasterDEMTile, onParsed) { RasterDEMTileTest test; RasterDEMTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset); - tile.onParsed(std::make_unique(PremultipliedImage({16, 16}), Tileset::DEMEncoding::Mapbox), 0); + tile.onParsed(std::make_unique(PremultipliedImage({16, 16}), Tileset::RasterEncoding::Mapbox), 0); EXPECT_TRUE(tile.isRenderable()); EXPECT_TRUE(tile.isLoaded()); EXPECT_TRUE(tile.isComplete()); diff --git a/test/tile/tile_cache.test.cpp b/test/tile/tile_cache.test.cpp index 076186a0b..210aab225 100644 --- a/test/tile/tile_cache.test.cpp +++ b/test/tile/tile_cache.test.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include @@ -38,6 +38,8 @@ public: renderable = true; } + void setData(const std::shared_ptr&) override {} + util::SimpleIdentity uniqueId; }; diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index fae330a8a..83e9dd2c9 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -1,7 +1,7 @@ #include #include -#include -#include +#include +#include #include #include @@ -25,7 +25,7 @@ using namespace mbgl; TEST(VectorTile, setError) { VectorTileTest test; - VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset); + VectorMVTTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset); tile.setError(std::make_exception_ptr(std::runtime_error("test"))); EXPECT_FALSE(tile.isRenderable()); EXPECT_TRUE(tile.isLoaded()); @@ -34,7 +34,7 @@ TEST(VectorTile, setError) { TEST(VectorTile, onError) { VectorTileTest test; - VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset); + VectorMVTTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset); tile.onError(std::make_exception_ptr(std::runtime_error("test")), 0); EXPECT_FALSE(tile.isRenderable()); @@ -44,7 +44,7 @@ TEST(VectorTile, onError) { TEST(VectorTile, Issue8542) { VectorTileTest test; - VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset); + VectorMVTTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset); // Query before data is set std::vector result; @@ -52,7 +52,7 @@ TEST(VectorTile, Issue8542) { } TEST(VectorTileData, ParseResults) { - VectorTileData data(std::make_shared(util::read_file("test/fixtures/map/issue12432/0-0-0.mvt"))); + VectorMVTTileData data(std::make_shared(util::read_file("test/fixtures/map/issue12432/0-0-0.mvt"))); std::vector layerNames = data.layerNames(); ASSERT_EQ(layerNames.size(), 2u); diff --git a/vendor/PMTiles b/vendor/PMTiles index 60f3331ca..e232df557 160000 --- a/vendor/PMTiles +++ b/vendor/PMTiles @@ -1 +1 @@ -Subproject commit 60f3331ca9d5cfa4fcdf1e076a3d3059aebb17bb +Subproject commit e232df55745642b39f0cc1edfc85df2633bce29c diff --git a/vendor/glslang b/vendor/glslang index 8a85691a0..a92c61f84 160000 --- a/vendor/glslang +++ b/vendor/glslang @@ -1 +1 @@ -Subproject commit 8a85691a0740d390761a1008b4696f57facd02c4 +Subproject commit a92c61f8456fa9731c0b000a2c6fc52a740c2be7 diff --git a/vendor/maplibre-tile-spec b/vendor/maplibre-tile-spec new file mode 160000 index 000000000..7e3cfe225 --- /dev/null +++ b/vendor/maplibre-tile-spec @@ -0,0 +1 @@ +Subproject commit 7e3cfe2251944b11dd3b0d1f7a6c4ebd3e047e2f diff --git a/vendor/maplibre-tile-spec.cmake b/vendor/maplibre-tile-spec.cmake new file mode 100644 index 000000000..68a1ba71f --- /dev/null +++ b/vendor/maplibre-tile-spec.cmake @@ -0,0 +1,15 @@ +set(MLT_WITH_JSON OFF CACHE BOOL "No JSON support" FORCE) +set(MLT_WITH_PROTOZERO OFF CACHE BOOL "No protozero" FORCE) +set(MLT_WITH_FASTPFOR OFF CACHE BOOL "disabled for lack of support for ARMv7 in SIMDE and requirement for SSE on x86" FORCE) +set(MLT_WITH_TESTS OFF CACHE BOOL "Google Test conflicts with Dawn") +set(MLT_WITH_TOOLS OFF CACHE BOOL "Not used") + +# This is set by the platform CMakeLists.txt after vendor libraries. If it was set earlier, we could just use it. +set(CMAKE_OSX_DEPLOYMENT_TARGET 14.3) +set(MLT_OSX_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET} CACHE STRING "Inherited MacOS/iOS target" FORCE) + +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25") + add_subdirectory(${PROJECT_SOURCE_DIR}/vendor/maplibre-tile-spec/cpp SYSTEM) +else() + add_subdirectory(${PROJECT_SOURCE_DIR}/vendor/maplibre-tile-spec/cpp) +endif()