diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson.hpp
deleted file mode 100644
index 4b62751e1..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-
-#include <mapbox/geometry.hpp>
-#include <mapbox/variant.hpp>
-
-namespace mapbox {
-namespace geojson {
-
-using value               = mapbox::geometry::value;
-using null_value_t        = mapbox::geometry::null_value_t;
-using identifier          = mapbox::geometry::identifier;
-using point               = mapbox::geometry::point<double>;
-using multi_point         = mapbox::geometry::multi_point<double>;
-using line_string         = mapbox::geometry::line_string<double>;
-using linear_ring         = mapbox::geometry::linear_ring<double>;
-using multi_line_string   = mapbox::geometry::multi_line_string<double>;
-using polygon             = mapbox::geometry::polygon<double>;
-using multi_polygon       = mapbox::geometry::multi_polygon<double>;
-using geometry            = mapbox::geometry::geometry<double>;
-using geometry_collection = mapbox::geometry::geometry_collection<double>;
-using feature             = mapbox::geometry::feature<double>;
-using feature_collection  = mapbox::geometry::feature_collection<double>;
-
-// Parse inputs of known types. Instantiations are provided for geometry, feature, and
-// feature_collection.
-template <class T>
-T parse(const std::string &);
-
-// Parse any GeoJSON type.
-using geojson = mapbox::util::variant<geometry, feature, feature_collection>;
-geojson parse(const std::string &);
-
-// Stringify inputs of known types. Instantiations are provided for geometry, feature, and
-// feature_collection.
-template <class T>
-std::string stringify(const T &);
-
-// Stringify any GeoJSON type.
-std::string stringify(const geojson &);
-
-} // namespace geojson
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson/rapidjson.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson/rapidjson.hpp
deleted file mode 100644
index 360eefd01..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson/rapidjson.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include <rapidjson/document.h>
-#include <mapbox/geojson.hpp>
-
-namespace mapbox {
-namespace geojson {
-
-// Use the CrtAllocator, because the MemoryPoolAllocator is broken on ARM
-// https://github.com/miloyip/rapidjson/issues/200, 301, 388
-using rapidjson_allocator = rapidjson::CrtAllocator;
-using rapidjson_document = rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson_allocator>;
-using rapidjson_value = rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson_allocator>;
-
-// Convert inputs of known types. Instantiations are provided for geometry, feature, and
-// feature_collection.
-template <typename T>
-T convert(const rapidjson_value &);
-
-// Convert any GeoJSON type.
-geojson convert(const rapidjson_value &);
-
-// Convert back to rapidjson value. Instantiations are provided for geometry, feature, and
-// feature_collection.
-template <typename T>
-rapidjson_value convert(const T &, rapidjson_allocator&);
-
-// Convert any GeoJSON type.
-rapidjson_value convert(const geojson &, rapidjson_allocator&);
-
-} // namespace geojson
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson_impl.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson_impl.hpp
deleted file mode 100644
index 48d81e411..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojson/0.4.2/include/mapbox/geojson_impl.hpp
+++ /dev/null
@@ -1,453 +0,0 @@
-#pragma once
-
-#include <mapbox/geojson.hpp>
-#include <mapbox/geojson/rapidjson.hpp>
-
-#include <rapidjson/document.h>
-#include <rapidjson/writer.h>
-#include <rapidjson/stringbuffer.h>
-#include <rapidjson/error/en.h>
-
-#include <sstream>
-
-namespace mapbox {
-namespace geojson {
-
-using error    = std::runtime_error;
-using prop_map = std::unordered_map<std::string, value>;
-
-template <typename T>
-T convert(const rapidjson_value &json);
-
-template <>
-point convert<point>(const rapidjson_value &json) {
-    if (json.Size() < 2)
-        throw error("coordinates array must have at least 2 numbers");
-
-    return point{ json[0].GetDouble(), json[1].GetDouble() };
-}
-
-template <typename Cont>
-Cont convert(const rapidjson_value &json) {
-    Cont points;
-    auto size = json.Size();
-    points.reserve(size);
-
-    for (auto &element : json.GetArray()) {
-        points.push_back(convert<typename Cont::value_type>(element));
-    }
-    return points;
-}
-
-template <>
-geometry convert<geometry>(const rapidjson_value &json) {
-    if (!json.IsObject())
-        throw error("Geometry must be an object");
-
-    const auto &json_end = json.MemberEnd();
-
-    const auto &type_itr = json.FindMember("type");
-    if (type_itr == json_end)
-        throw error("Geometry must have a type property");
-
-    const auto &type = type_itr->value;
-
-    if (type == "GeometryCollection") {
-        const auto &geometries_itr = json.FindMember("geometries");
-        if (geometries_itr == json_end)
-            throw error("GeometryCollection must have a geometries property");
-
-        const auto &json_geometries = geometries_itr->value;
-
-        if (!json_geometries.IsArray())
-            throw error("GeometryCollection geometries property must be an array");
-
-        return geometry{ convert<geometry_collection>(json_geometries) };
-    }
-
-    const auto &coords_itr = json.FindMember("coordinates");
-
-    if (coords_itr == json_end)
-        throw error(std::string(type.GetString()) + " geometry must have a coordinates property");
-
-    const auto &json_coords = coords_itr->value;
-    if (!json_coords.IsArray())
-        throw error("coordinates property must be an array");
-
-    if (type == "Point")
-        return geometry{ convert<point>(json_coords) };
-    if (type == "MultiPoint")
-        return geometry{ convert<multi_point>(json_coords) };
-    if (type == "LineString")
-        return geometry{ convert<line_string>(json_coords) };
-    if (type == "MultiLineString")
-        return geometry{ convert<multi_line_string>(json_coords) };
-    if (type == "Polygon")
-        return geometry{ convert<polygon>(json_coords) };
-    if (type == "MultiPolygon")
-        return geometry{ convert<multi_polygon>(json_coords) };
-
-    throw error(std::string(type.GetString()) + " not yet implemented");
-}
-
-template <>
-value convert<value>(const rapidjson_value &json);
-
-template <>
-prop_map convert(const rapidjson_value &json) {
-    if (!json.IsObject())
-        throw error("properties must be an object");
-
-    prop_map result;
-    for (auto &member : json.GetObject()) {
-        result.emplace(std::string(member.name.GetString(), member.name.GetStringLength()),
-                       convert<value>(member.value));
-    }
-    return result;
-}
-
-template <>
-value convert<value>(const rapidjson_value &json) {
-    switch (json.GetType()) {
-    case rapidjson::kNullType:
-        return ::mapbox::geometry::null_value_t{};
-    case rapidjson::kFalseType:
-        return false;
-    case rapidjson::kTrueType:
-        return true;
-    case rapidjson::kObjectType:
-        return convert<prop_map>(json);
-    case rapidjson::kArrayType:
-        return convert<std::vector<value>>(json);
-    case rapidjson::kStringType:
-        return std::string(json.GetString(), json.GetStringLength());
-    default:
-        assert(json.GetType() == rapidjson::kNumberType);
-        if (json.IsUint64())
-            return std::uint64_t(json.GetUint64());
-        if (json.IsInt64())
-            return std::int64_t(json.GetInt64());
-        return json.GetDouble();
-    }
-}
-
-template <>
-identifier convert<identifier>(const rapidjson_value &json) {
-    switch (json.GetType()) {
-    case rapidjson::kStringType:
-        return std::string(json.GetString(), json.GetStringLength());
-    case rapidjson::kNumberType:
-        if (json.IsUint64())
-            return std::uint64_t(json.GetUint64());
-        if (json.IsInt64())
-            return std::int64_t(json.GetInt64());
-        return json.GetDouble();
-    default:
-        throw error("Feature id must be a string or number");
-    }
-}
-
-template <>
-feature convert<feature>(const rapidjson_value &json) {
-    if (!json.IsObject())
-        throw error("Feature must be an object");
-
-    auto const &json_end = json.MemberEnd();
-    auto const &type_itr = json.FindMember("type");
-
-    if (type_itr == json_end)
-        throw error("Feature must have a type property");
-    if (type_itr->value != "Feature")
-        throw error("Feature type must be Feature");
-
-    auto const &geom_itr = json.FindMember("geometry");
-
-    if (geom_itr == json_end)
-        throw error("Feature must have a geometry property");
-
-    feature result{ convert<geometry>(geom_itr->value) };
-
-    auto const &id_itr = json.FindMember("id");
-    if (id_itr != json_end) {
-        result.id = convert<identifier>(id_itr->value);
-    }
-
-    auto const &prop_itr = json.FindMember("properties");
-    if (prop_itr != json_end) {
-        const auto &json_props = prop_itr->value;
-        if (!json_props.IsNull()) {
-            result.properties = convert<prop_map>(json_props);
-        }
-    }
-
-    return result;
-}
-
-template <>
-geojson convert<geojson>(const rapidjson_value &json) {
-    if (!json.IsObject())
-        throw error("GeoJSON must be an object");
-
-    const auto &type_itr = json.FindMember("type");
-    const auto &json_end = json.MemberEnd();
-
-    if (type_itr == json_end)
-        throw error("GeoJSON must have a type property");
-
-    const auto &type = type_itr->value;
-
-    if (type == "FeatureCollection") {
-        const auto &features_itr = json.FindMember("features");
-        if (features_itr == json_end)
-            throw error("FeatureCollection must have features property");
-
-        const auto &json_features = features_itr->value;
-
-        if (!json_features.IsArray())
-            throw error("FeatureCollection features property must be an array");
-
-        feature_collection collection;
-
-        const auto &size = json_features.Size();
-        collection.reserve(size);
-
-        for (auto &feature_obj : json_features.GetArray()) {
-            collection.push_back(convert<feature>(feature_obj));
-        }
-
-        return geojson{ collection };
-    }
-
-    if (type == "Feature")
-        return geojson{ convert<feature>(json) };
-
-    return geojson{ convert<geometry>(json) };
-}
-
-template <class T>
-T parse(const std::string &json) {
-    rapidjson_document d;
-    d.Parse(json.c_str());
-    if (d.HasParseError()) {
-        std::stringstream message;
-        message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError());
-        throw error(message.str());
-    }
-    return convert<T>(d);
-}
-
-template <>
-geometry parse<geometry>(const std::string &);
-template <>
-feature parse<feature>(const std::string &);
-template <>
-feature_collection parse<feature_collection>(const std::string &);
-
-geojson parse(const std::string &json) {
-    return parse<geojson>(json);
-}
-
-geojson convert(const rapidjson_value &json) {
-    return convert<geojson>(json);
-}
-
-template <>
-rapidjson_value convert<geometry>(const geometry&, rapidjson_allocator&);
-
-template <>
-rapidjson_value convert<feature>(const feature&, rapidjson_allocator&);
-
-template <>
-rapidjson_value convert<feature_collection>(const feature_collection&, rapidjson_allocator&);
-
-struct to_type {
-public:
-    const char * operator()(const point&) {
-        return "Point";
-    }
-
-    const char * operator()(const line_string&) {
-        return "LineString";
-    }
-
-    const char * operator()(const polygon&) {
-        return "Polygon";
-    }
-
-    const char * operator()(const multi_point&) {
-        return "MultiPoint";
-    }
-
-    const char * operator()(const multi_line_string&) {
-        return "MultiLineString";
-    }
-
-    const char * operator()(const multi_polygon&) {
-        return "MultiPolygon";
-    }
-
-    const char * operator()(const geometry_collection&) {
-        return "GeometryCollection";
-    }
-};
-
-struct to_coordinates_or_geometries {
-    rapidjson_allocator& allocator;
-
-    // Handles line_string, polygon, multi_point, multi_line_string, multi_polygon, and geometry_collection.
-    template <class E>
-    rapidjson_value operator()(const std::vector<E>& vector) {
-        rapidjson_value result;
-        result.SetArray();
-        for (std::size_t i = 0; i < vector.size(); ++i) {
-            result.PushBack(operator()(vector[i]), allocator);
-        }
-        return result;
-    }
-
-    rapidjson_value operator()(const point& element) {
-        rapidjson_value result;
-        result.SetArray();
-        result.PushBack(element.x, allocator);
-        result.PushBack(element.y, allocator);
-        return result;
-    }
-
-    rapidjson_value operator()(const geometry& element) {
-        return convert(element, allocator);
-    }
-};
-
-struct to_value {
-    rapidjson_allocator& allocator;
-
-    rapidjson_value operator()(null_value_t) {
-        rapidjson_value result;
-        result.SetNull();
-        return result;
-    }
-
-    rapidjson_value operator()(bool t) {
-        rapidjson_value result;
-        result.SetBool(t);
-        return result;
-    }
-
-    rapidjson_value operator()(int64_t t) {
-        rapidjson_value result;
-        result.SetInt64(t);
-        return result;
-    }
-
-    rapidjson_value operator()(uint64_t t) {
-        rapidjson_value result;
-        result.SetUint64(t);
-        return result;
-    }
-
-    rapidjson_value operator()(double t) {
-        rapidjson_value result;
-        result.SetDouble(t);
-        return result;
-    }
-
-    rapidjson_value operator()(const std::string& t) {
-        rapidjson_value result;
-        result.SetString(t.data(), rapidjson::SizeType(t.size()), allocator);
-        return result;
-    }
-
-    rapidjson_value operator()(const std::vector<value>& array) {
-        rapidjson_value result;
-        result.SetArray();
-        for (const auto& item : array) {
-            result.PushBack(value::visit(item, *this), allocator);
-        }
-        return result;
-    }
-
-    rapidjson_value operator()(const std::unordered_map<std::string, value>& map) {
-        rapidjson_value result;
-        result.SetObject();
-        for (const auto& property : map) {
-            result.AddMember(
-                rapidjson::GenericStringRef<char> {
-                    property.first.data(),
-                    rapidjson::SizeType(property.first.size())
-                },
-                value::visit(property.second, *this),
-                allocator);
-        }
-        return result;
-    }
-};
-
-template <>
-rapidjson_value convert<geometry>(const geometry& element, rapidjson_allocator& allocator) {
-    rapidjson_value result(rapidjson::kObjectType);
-
-    result.AddMember(
-        "type",
-        rapidjson::GenericStringRef<char> { geometry::visit(element, to_type()) },
-        allocator);
-
-    result.AddMember(
-        rapidjson::GenericStringRef<char> { element.is<geometry_collection>() ? "geometries" : "coordinates" },
-        geometry::visit(element, to_coordinates_or_geometries { allocator }),
-        allocator);
-
-    return result;
-}
-
-template <>
-rapidjson_value convert<feature>(const feature& element, rapidjson_allocator& allocator) {
-    rapidjson_value result(rapidjson::kObjectType);
-    result.AddMember("type", "Feature", allocator);
-
-    if (element.id) {
-        result.AddMember("id", identifier::visit(*element.id, to_value { allocator }), allocator);
-    }
-
-    result.AddMember("geometry", convert(element.geometry, allocator), allocator);
-    result.AddMember("properties", to_value { allocator }(element.properties), allocator);
-
-    return result;
-}
-
-template <>
-rapidjson_value convert<feature_collection>(const feature_collection& collection, rapidjson_allocator& allocator) {
-    rapidjson_value result(rapidjson::kObjectType);
-    result.AddMember("type", "FeatureCollection", allocator);
-
-    rapidjson_value features(rapidjson::kArrayType);
-    for (const auto& element : collection) {
-        features.PushBack(convert(element, allocator), allocator);
-    }
-    result.AddMember("features", features, allocator);
-
-    return result;
-}
-
-rapidjson_value convert(const geojson& element, rapidjson_allocator& allocator) {
-    return geojson::visit(element, [&] (const auto& alternative) {
-        return convert(alternative, allocator);
-    });
-}
-
-template <class T>
-std::string stringify(const T& t) {
-    rapidjson_allocator allocator;
-    rapidjson::StringBuffer buffer;
-    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
-    convert(t, allocator).Accept(writer);
-    return buffer.GetString();
-}
-
-std::string stringify(const geojson& element) {
-    return geojson::visit(element, [] (const auto& alternative) {
-        return stringify(alternative);
-    });
-}
-
-} // namespace geojson
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson.hpp
new file mode 100644
index 000000000..7cff16241
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <mapbox/geometry.hpp>
+#include <mapbox/feature.hpp>
+#include <mapbox/variant.hpp>
+
+namespace mapbox {
+namespace geojson {
+
+using empty               = mapbox::geometry::empty;
+using point               = mapbox::geometry::point<double>;
+using multi_point         = mapbox::geometry::multi_point<double>;
+using line_string         = mapbox::geometry::line_string<double>;
+using linear_ring         = mapbox::geometry::linear_ring<double>;
+using multi_line_string   = mapbox::geometry::multi_line_string<double>;
+using polygon             = mapbox::geometry::polygon<double>;
+using multi_polygon       = mapbox::geometry::multi_polygon<double>;
+using geometry            = mapbox::geometry::geometry<double>;
+using geometry_collection = mapbox::geometry::geometry_collection<double>;
+
+using value               = mapbox::feature::value;
+using null_value_t        = mapbox::feature::null_value_t;
+using identifier          = mapbox::feature::identifier;
+using feature             = mapbox::feature::feature<double>;
+using feature_collection  = mapbox::feature::feature_collection<double>;
+
+// Parse inputs of known types. Instantiations are provided for geometry, feature, and
+// feature_collection.
+template <class T>
+T parse(const std::string &);
+
+// Parse any GeoJSON type.
+using geojson = mapbox::util::variant<geometry, feature, feature_collection>;
+geojson parse(const std::string &);
+
+// Stringify inputs of known types. Instantiations are provided for geometry, feature, and
+// feature_collection.
+template <class T>
+std::string stringify(const T &);
+
+// Stringify any GeoJSON type.
+std::string stringify(const geojson &);
+
+} // namespace geojson
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson/rapidjson.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson/rapidjson.hpp
new file mode 100644
index 000000000..360eefd01
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson/rapidjson.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <rapidjson/document.h>
+#include <mapbox/geojson.hpp>
+
+namespace mapbox {
+namespace geojson {
+
+// Use the CrtAllocator, because the MemoryPoolAllocator is broken on ARM
+// https://github.com/miloyip/rapidjson/issues/200, 301, 388
+using rapidjson_allocator = rapidjson::CrtAllocator;
+using rapidjson_document = rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson_allocator>;
+using rapidjson_value = rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson_allocator>;
+
+// Convert inputs of known types. Instantiations are provided for geometry, feature, and
+// feature_collection.
+template <typename T>
+T convert(const rapidjson_value &);
+
+// Convert any GeoJSON type.
+geojson convert(const rapidjson_value &);
+
+// Convert back to rapidjson value. Instantiations are provided for geometry, feature, and
+// feature_collection.
+template <typename T>
+rapidjson_value convert(const T &, rapidjson_allocator&);
+
+// Convert any GeoJSON type.
+rapidjson_value convert(const geojson &, rapidjson_allocator&);
+
+} // namespace geojson
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson/value.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson/value.hpp
new file mode 100644
index 000000000..128331d0a
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson/value.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <mapbox/geojson.hpp>
+
+namespace mapbox {
+namespace geojson {
+
+// Converts Value to GeoJSON type.
+geojson convert(const mapbox::geojson::value&);
+
+// Converts GeoJSON type to Value.
+mapbox::geojson::value convert(const geojson&);
+
+} // namespace geojson
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson_impl.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson_impl.hpp
new file mode 100644
index 000000000..621a86cdf
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson_impl.hpp
@@ -0,0 +1,508 @@
+#pragma once
+
+#include <mapbox/geojson.hpp>
+#include <mapbox/geojson/rapidjson.hpp>
+
+#include <rapidjson/document.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/error/en.h>
+
+#include <sstream>
+
+namespace mapbox {
+namespace geojson {
+
+using error    = std::runtime_error;
+using prop_map = std::unordered_map<std::string, value>;
+
+void validatePolygon(const rapidjson_value &json) {
+    // this check is required incase case of multipolygon validation
+    if (!json.IsArray()) {
+        throw error("Coordinates must be nested more deeply.");
+    }
+    for (auto &element : json.GetArray()) {
+        if (!element.IsArray()) {
+            throw error("Coordinates must be an array of arrays, each describing a polygon.");
+        }
+        if (element.Size() < 4){
+            throw error("Polygon must be described by 4 or more coordinate points. Improper "
+                        "nesting can also lead to this error. Double check that the coordinates "
+                        "are properly nested and there are 4 or more coordinates.");
+        }
+    }
+}
+
+void validateLineString(const rapidjson_value &json) {
+    if (json.GetArray().Size() < 2) {
+        throw error("A line string must have two or more coordinate points.");
+    }
+}
+
+template <typename T>
+T convert(const rapidjson_value &json);
+
+template <>
+point convert<point>(const rapidjson_value &json) {
+    if (!json.IsArray()) {
+        throw error("coordinates must be an array.");
+    }
+    if (json.Size() < 2)
+        throw error("coordinates array must have at least 2 numbers");
+
+    return point{ json[0].GetDouble(), json[1].GetDouble() };
+}
+
+template <typename Cont>
+Cont convert(const rapidjson_value &json) {
+    Cont points;
+    if (!json.IsArray()) {
+        throw error("coordinates must be an array of points describing linestring or an array of "
+                    "arrays describing polygons and line strings.");
+    }
+    auto size = json.Size();
+    points.reserve(size);
+
+    for (auto &element : json.GetArray()) {
+        points.push_back(convert<typename Cont::value_type>(element));
+    }
+    return points;
+}
+
+template <>
+geometry convert<geometry>(const rapidjson_value &json) {
+    if (json.IsNull())
+        return empty{};
+
+    if (!json.IsObject())
+        throw error("Geometry must be an object");
+
+    const auto &json_end = json.MemberEnd();
+
+    const auto &type_itr = json.FindMember("type");
+    if (type_itr == json_end)
+        throw error("Geometry must have a type property");
+
+    const auto &type = type_itr->value;
+
+    if (type == "GeometryCollection") {
+        const auto &geometries_itr = json.FindMember("geometries");
+        if (geometries_itr == json_end)
+            throw error("GeometryCollection must have a geometries property");
+
+        const auto &json_geometries = geometries_itr->value;
+
+        if (!json_geometries.IsArray())
+            throw error("GeometryCollection geometries property must be an array");
+
+        return geometry{ convert<geometry_collection>(json_geometries) };
+    }
+
+    const auto &coords_itr = json.FindMember("coordinates");
+
+    if (coords_itr == json_end)
+        throw error(std::string(type.GetString()) + " geometry must have a coordinates property");
+
+    const auto &json_coords = coords_itr->value;
+    if (!json_coords.IsArray())
+        throw error("coordinates property must be an array");
+
+    if (type == "Point")
+        return geometry{ convert<point>(json_coords) };
+    if (type == "MultiPoint")
+        return geometry{ convert<multi_point>(json_coords) };
+    if (type == "LineString") {
+        validateLineString(json_coords);
+        return geometry{ convert<line_string>(json_coords) };
+    }
+    if (type == "MultiLineString") {
+        for (auto &element : json_coords.GetArray()) {
+            validateLineString(element);
+        }
+        return geometry{ convert<multi_line_string>(json_coords) };
+    }
+    if (type == "Polygon") {
+        validatePolygon(json_coords);
+        return geometry{ convert<polygon>(json_coords) };
+    }
+    if (type == "MultiPolygon") {
+        for (auto &element: json_coords.GetArray()) {
+            validatePolygon(element);
+        }
+        return geometry{ convert<multi_polygon>(json_coords) };
+    }
+    throw error(std::string(type.GetString()) + " not yet implemented");
+}
+
+template <>
+value convert<value>(const rapidjson_value &json);
+
+template <>
+prop_map convert(const rapidjson_value &json) {
+    if (!json.IsObject())
+        throw error("properties must be an object");
+
+    prop_map result;
+    for (auto &member : json.GetObject()) {
+        result.emplace(std::string(member.name.GetString(), member.name.GetStringLength()),
+                       convert<value>(member.value));
+    }
+    return result;
+}
+
+template <>
+value convert<value>(const rapidjson_value &json) {
+    switch (json.GetType()) {
+    case rapidjson::kNullType:
+        return null_value_t{};
+    case rapidjson::kFalseType:
+        return false;
+    case rapidjson::kTrueType:
+        return true;
+    case rapidjson::kObjectType:
+        return convert<prop_map>(json);
+    case rapidjson::kArrayType:
+        return convert<std::vector<value>>(json);
+    case rapidjson::kStringType:
+        return std::string(json.GetString(), json.GetStringLength());
+    default:
+        assert(json.GetType() == rapidjson::kNumberType);
+        if (json.IsUint64())
+            return std::uint64_t(json.GetUint64());
+        if (json.IsInt64())
+            return std::int64_t(json.GetInt64());
+        return json.GetDouble();
+    }
+}
+
+template <>
+identifier convert<identifier>(const rapidjson_value &json) {
+    switch (json.GetType()) {
+    case rapidjson::kStringType:
+        return std::string(json.GetString(), json.GetStringLength());
+    case rapidjson::kNumberType:
+        if (json.IsUint64())
+            return std::uint64_t(json.GetUint64());
+        if (json.IsInt64())
+            return std::int64_t(json.GetInt64());
+        return json.GetDouble();
+    default:
+        throw error("Feature id must be a string or number");
+    }
+}
+
+template <>
+feature convert<feature>(const rapidjson_value &json) {
+    if (!json.IsObject())
+        throw error("Feature must be an object");
+
+    auto const &json_end = json.MemberEnd();
+    auto const &type_itr = json.FindMember("type");
+
+    if (type_itr == json_end)
+        throw error("Feature must have a type property");
+    if (type_itr->value != "Feature")
+        throw error("Feature type must be Feature");
+
+    auto const &geom_itr = json.FindMember("geometry");
+
+    if (geom_itr == json_end)
+        throw error("Feature must have a geometry property");
+
+    feature result{ convert<geometry>(geom_itr->value) };
+
+    auto const &id_itr = json.FindMember("id");
+    if (id_itr != json_end) {
+        result.id = convert<identifier>(id_itr->value);
+    }
+
+    auto const &prop_itr = json.FindMember("properties");
+    if (prop_itr != json_end) {
+        const auto &json_props = prop_itr->value;
+        if (!json_props.IsNull()) {
+            result.properties = convert<prop_map>(json_props);
+        }
+    }
+
+    return result;
+}
+
+template <>
+geojson convert<geojson>(const rapidjson_value &json) {
+    if (!json.IsObject())
+        throw error("GeoJSON must be an object");
+
+    const auto &type_itr = json.FindMember("type");
+    const auto &json_end = json.MemberEnd();
+
+    if (type_itr == json_end)
+        throw error("GeoJSON must have a type property");
+
+    const auto &type = type_itr->value;
+
+    if (type == "FeatureCollection") {
+        const auto &features_itr = json.FindMember("features");
+        if (features_itr == json_end)
+            throw error("FeatureCollection must have features property");
+
+        const auto &json_features = features_itr->value;
+
+        if (!json_features.IsArray())
+            throw error("FeatureCollection features property must be an array");
+
+        feature_collection collection;
+
+        const auto &size = json_features.Size();
+        collection.reserve(size);
+
+        for (auto &feature_obj : json_features.GetArray()) {
+            collection.push_back(convert<feature>(feature_obj));
+        }
+
+        return geojson{ collection };
+    }
+
+    if (type == "Feature")
+        return geojson{ convert<feature>(json) };
+
+    return geojson{ convert<geometry>(json) };
+}
+
+template <class T>
+T parse(const std::string &json) {
+    rapidjson_document d;
+    d.Parse(json.c_str());
+    if (d.HasParseError()) {
+        std::stringstream message;
+        message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError());
+        throw error(message.str());
+    }
+    return convert<T>(d);
+}
+
+template <>
+geometry parse<geometry>(const std::string &);
+template <>
+feature parse<feature>(const std::string &);
+template <>
+feature_collection parse<feature_collection>(const std::string &);
+
+geojson parse(const std::string &json) {
+    return parse<geojson>(json);
+}
+
+geojson convert(const rapidjson_value &json) {
+    return convert<geojson>(json);
+}
+
+template <>
+rapidjson_value convert<geometry>(const geometry&, rapidjson_allocator&);
+
+template <>
+rapidjson_value convert<feature>(const feature&, rapidjson_allocator&);
+
+template <>
+rapidjson_value convert<feature_collection>(const feature_collection&, rapidjson_allocator&);
+
+struct to_type {
+public:
+    const char * operator()(const empty&) {
+        abort();
+    }
+
+    const char * operator()(const point&) {
+        return "Point";
+    }
+
+    const char * operator()(const line_string&) {
+        return "LineString";
+    }
+
+    const char * operator()(const polygon&) {
+        return "Polygon";
+    }
+
+    const char * operator()(const multi_point&) {
+        return "MultiPoint";
+    }
+
+    const char * operator()(const multi_line_string&) {
+        return "MultiLineString";
+    }
+
+    const char * operator()(const multi_polygon&) {
+        return "MultiPolygon";
+    }
+
+    const char * operator()(const geometry_collection&) {
+        return "GeometryCollection";
+    }
+};
+
+struct to_coordinates_or_geometries {
+    rapidjson_allocator& allocator;
+
+    // Handles line_string, polygon, multi_point, multi_line_string, multi_polygon, and geometry_collection.
+    template <class E>
+    rapidjson_value operator()(const std::vector<E>& vector) {
+        rapidjson_value result;
+        result.SetArray();
+        for (std::size_t i = 0; i < vector.size(); ++i) {
+            result.PushBack(operator()(vector[i]), allocator);
+        }
+        return result;
+    }
+
+    rapidjson_value operator()(const point& element) {
+        rapidjson_value result;
+        result.SetArray();
+        result.PushBack(element.x, allocator);
+        result.PushBack(element.y, allocator);
+        return result;
+    }
+
+    rapidjson_value operator()(const empty&) {
+        abort();
+    }
+
+    rapidjson_value operator()(const geometry& element) {
+        return convert(element, allocator);
+    }
+};
+
+struct to_value {
+    rapidjson_allocator& allocator;
+
+    rapidjson_value operator()(null_value_t) {
+        rapidjson_value result;
+        result.SetNull();
+        return result;
+    }
+
+    rapidjson_value operator()(bool t) {
+        rapidjson_value result;
+        result.SetBool(t);
+        return result;
+    }
+
+    rapidjson_value operator()(int64_t t) {
+        rapidjson_value result;
+        result.SetInt64(t);
+        return result;
+    }
+
+    rapidjson_value operator()(uint64_t t) {
+        rapidjson_value result;
+        result.SetUint64(t);
+        return result;
+    }
+
+    rapidjson_value operator()(double t) {
+        rapidjson_value result;
+        result.SetDouble(t);
+        return result;
+    }
+
+    rapidjson_value operator()(const std::string& t) {
+        rapidjson_value result;
+        result.SetString(t.data(), rapidjson::SizeType(t.size()), allocator);
+        return result;
+    }
+
+    rapidjson_value operator()(const std::vector<value>& array) {
+        rapidjson_value result;
+        result.SetArray();
+        for (const auto& item : array) {
+            result.PushBack(value::visit(item, *this), allocator);
+        }
+        return result;
+    }
+
+    rapidjson_value operator()(const std::unordered_map<std::string, value>& map) {
+        rapidjson_value result;
+        result.SetObject();
+        for (const auto& property : map) {
+            result.AddMember(
+                rapidjson::GenericStringRef<char> {
+                    property.first.data(),
+                    rapidjson::SizeType(property.first.size())
+                },
+                value::visit(property.second, *this),
+                allocator);
+        }
+        return result;
+    }
+};
+
+template <>
+rapidjson_value convert<geometry>(const geometry& element, rapidjson_allocator& allocator) {
+    if (element.is<empty>())
+        return rapidjson_value(rapidjson::kNullType);
+
+    rapidjson_value result(rapidjson::kObjectType);
+
+    result.AddMember(
+        "type",
+        rapidjson::GenericStringRef<char> { geometry::visit(element, to_type()) },
+        allocator);
+
+    result.AddMember(
+        rapidjson::GenericStringRef<char> { element.is<geometry_collection>() ? "geometries" : "coordinates" },
+        geometry::visit(element, to_coordinates_or_geometries { allocator }),
+        allocator);
+
+    return result;
+}
+
+template <>
+rapidjson_value convert<feature>(const feature& element, rapidjson_allocator& allocator) {
+    rapidjson_value result(rapidjson::kObjectType);
+    result.AddMember("type", "Feature", allocator);
+
+    if (!element.id.is<null_value_t>()) {
+        result.AddMember("id", identifier::visit(element.id, to_value { allocator }), allocator);
+    }
+
+    result.AddMember("geometry", convert(element.geometry, allocator), allocator);
+    result.AddMember("properties", to_value { allocator }(element.properties), allocator);
+
+    return result;
+}
+
+template <>
+rapidjson_value convert<feature_collection>(const feature_collection& collection, rapidjson_allocator& allocator) {
+    rapidjson_value result(rapidjson::kObjectType);
+    result.AddMember("type", "FeatureCollection", allocator);
+
+    rapidjson_value features(rapidjson::kArrayType);
+    for (const auto& element : collection) {
+        features.PushBack(convert(element, allocator), allocator);
+    }
+    result.AddMember("features", features, allocator);
+
+    return result;
+}
+
+rapidjson_value convert(const geojson& element, rapidjson_allocator& allocator) {
+    return geojson::visit(element, [&] (const auto& alternative) {
+        return convert(alternative, allocator);
+    });
+}
+
+template <class T>
+std::string stringify(const T& t) {
+    rapidjson_allocator allocator;
+    rapidjson::StringBuffer buffer;
+    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+    convert(t, allocator).Accept(writer);
+    return buffer.GetString();
+}
+
+std::string stringify(const geojson& element) {
+    return geojson::visit(element, [] (const auto& alternative) {
+        return stringify(alternative);
+    });
+}
+
+} // namespace geojson
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson_value_impl.hpp b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson_value_impl.hpp
new file mode 100644
index 000000000..699c348e2
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojson/0.5.1/include/mapbox/geojson_value_impl.hpp
@@ -0,0 +1,308 @@
+#pragma once
+
+#include <mapbox/geojson.hpp>
+#include <mapbox/geojson/value.hpp>
+
+namespace mapbox {
+namespace geojson {
+
+using error = std::runtime_error;
+
+namespace {
+
+double getDouble(const value& numVal) {
+    return numVal.match([](double n) { return n; },
+                        [](uint64_t n) { return n; },
+                        [](int64_t n) { return n; },
+                        [](const auto &) -> double {
+                            throw error("coordinate's value must be of a Number type");
+                        });
+}
+
+} // namespace
+
+template <typename T>
+T convert(const value &);
+
+template <>
+point convert<point>(const value &val) {
+    assert(val.is<value::array_type>());
+    if (!val.is<value::array_type>()) {
+        throw error("coordinates must be of an Array type");
+    }
+
+    const auto &valuePoint = *val.getArray();
+    if (valuePoint.size() < 2) {
+        throw error("coordinates array must have at least 2 numbers");
+    }
+
+    return point{ getDouble(valuePoint[0]), getDouble(valuePoint[1]) };
+}
+
+template <typename Container>
+Container convert(const value &val) {
+    assert(val.is<value::array_type>());
+    if (!val.is<value::array_type>()) {
+        throw error("coordinates must be of an Array type");
+    }
+
+    const auto &pointArray = *val.getArray();
+    Container points;
+    points.reserve(pointArray.size());
+    for (const auto &p : pointArray) {
+        points.push_back(convert<typename Container::value_type>(p));
+    }
+    return points;
+}
+
+template <>
+geometry convert<geometry>(const value &val) {
+    auto *valueObject = val.getObject();
+    if (!valueObject) {
+        throw error("GeoJSON must be an object");
+    }
+
+    auto typeIt = valueObject->find("type");
+    if (typeIt == valueObject->end()) {
+        throw error("Geometry must have a type property");
+    }
+
+    const auto &typeValue = typeIt->second;
+    if (!typeValue.is<std::string>()) {
+        throw error("Geometry 'type' property must be of a String type");
+    }
+
+    const auto &typeString = *typeValue.getString();
+
+    if (typeString == "GeometryCollection") {
+        auto geometriesIt = valueObject->find("geometries");
+        if (geometriesIt == valueObject->end()) {
+            throw error("GeometryCollection must have a geometries property");
+        }
+
+        const auto *geometryArray = geometriesIt->second.getArray();
+        if (!geometryArray) {
+            throw error("GeometryCollection geometries property must be an array");
+        }
+
+        return geometry{ convert<geometry_collection>(*geometryArray) };
+    }
+
+    auto coordinatesIt = valueObject->find("coordinates");
+    if (coordinatesIt == valueObject->end()) {
+        throw error(typeString + " geometry must have a coordinates property");
+    }
+
+    const auto *coordinateArray = coordinatesIt->second.getArray();
+    if (!coordinateArray) {
+        throw error("coordinates property must be an array");
+    }
+
+    if (typeString == "Point")
+        return geometry{ convert<point>(*coordinateArray) };
+    if (typeString == "MultiPoint")
+        return geometry{ convert<multi_point>(*coordinateArray) };
+    if (typeString == "LineString")
+        return geometry{ convert<line_string>(*coordinateArray) };
+    if (typeString == "MultiLineString")
+        return geometry{ convert<multi_line_string>(*coordinateArray) };
+    if (typeString == "Polygon")
+        return geometry{ convert<polygon>(*coordinateArray) };
+    if (typeString == "MultiPolygon")
+        return geometry{ convert<multi_polygon>(*coordinateArray) };
+
+    throw error(typeString + " not yet implemented");
+}
+
+template <>
+feature convert<feature>(const value &val) {
+    auto *valueObject = val.getObject();
+    if (!valueObject) {
+        throw error("GeoJSON must be an object");
+    }
+
+    auto typeIt = valueObject->find("type");
+    if (typeIt == valueObject->end()) {
+        throw error("Feature must have a type property");
+    }
+
+    const auto &typeValue = typeIt->second;
+    if (!typeValue.is<std::string>()) {
+        throw error("Feature 'type' property must be of a String type");
+    }
+
+    if (*typeValue.getString() != "Feature") {
+        throw error("Feature type must be Feature");
+    }
+
+    auto geometryIt = valueObject->find("geometry");
+    if (geometryIt == valueObject->end()) {
+        throw error("Feature must have a geometry property");
+    }
+
+    feature result{ convert<geometry>(geometryIt->second) };
+    auto idIt = valueObject->find("id");
+    if (idIt != valueObject->end()) {
+        result.id =
+            idIt->second.match([](const std::string &string) -> identifier { return { string }; },
+                               [](int64_t number) -> identifier { return { number }; },
+                               [](uint64_t number) -> identifier { return { number }; },
+                               [](double number) -> identifier { return { number }; },
+                               [](const auto &) -> identifier {
+                                   throw error("Feature id must be a string or number");
+                               });
+    }
+
+    auto propertiesIt = valueObject->find("properties");
+    if (propertiesIt != valueObject->end() &&
+        !propertiesIt->second.is<mapbox::geojson::null_value_t>()) {
+        if (!propertiesIt->second.is<value::object_type>()) {
+            throw error("properties must be an object");
+        }
+        result.properties = *propertiesIt->second.getObject();
+    }
+
+    return result;
+}
+
+template <>
+geojson convert<geojson>(const value &val) {
+    auto *valueObject = val.getObject();
+    if (!valueObject) {
+        throw error("GeoJSON must be an object");
+    }
+
+    auto typeIt = valueObject->find("type");
+    if (typeIt == valueObject->end()) {
+        throw error("GeoJSON must have a type property");
+    }
+
+    const auto &typeValue = typeIt->second;
+    if (!typeValue.is<std::string>()) {
+        throw error("GeoJSON 'type' property must be of a String type");
+    }
+
+    const auto &typeString = *typeValue.getString();
+    if (typeString == "FeatureCollection") {
+        auto featuresIt = valueObject->find("features");
+        if (featuresIt == valueObject->end()) {
+            throw error("FeatureCollection must have features property");
+        }
+
+        const auto *featureArray = featuresIt->second.getArray();
+        if (!featureArray) {
+            throw error("FeatureCollection features property must be an array");
+        }
+
+        feature_collection collection;
+        collection.reserve(featureArray->size());
+        for (const auto &featureValue : *featureArray) {
+            collection.push_back(convert<feature>(featureValue));
+        }
+        return geojson{ collection };
+    }
+
+    if (typeString == "Feature") {
+        return geojson{ convert<feature>(val) };
+    }
+
+    return geojson{ convert<geometry>(val) };
+}
+
+geojson convert(const value &val) {
+    return val.match(
+        [](const null_value_t &) -> geojson { return geometry{}; },
+        [](const std::string &jsonString) {
+            return jsonString == "null" ? geometry{} : parse(jsonString);
+        },
+        [](const value::object_type &jsonObject) {
+            return convert<geojson>(static_cast<const mapbox::geojson::value &>(jsonObject));
+        },
+        [](const auto &) -> geojson { throw error("Invalid GeoJSON value was provided."); });
+}
+
+value convert(const point &p) {
+    return value::array_type{ p.x, p.y };
+}
+
+template <typename Cont>
+value convert(const Cont &points) {
+    value::array_type result;
+    result.reserve(points.size());
+    for (const auto &p : points) {
+        result.emplace_back(convert(p));
+    }
+    return result;
+}
+
+value convert(const geometry &geom) {
+    return geom.match(
+        [](const empty &) { return value{}; },
+        [](const point &p) {
+            return value::object_type{ { "type", "Point" }, { "coordinates", convert(p) } };
+        },
+        [](const multi_point &mp) {
+            return value::object_type{ { "type", "MultiPoint" }, { "coordinates", convert(mp) } };
+        },
+        [](const line_string &ls) {
+            return value::object_type{ { "type", "LineString" }, { "coordinates", convert(ls) } };
+        },
+        [](const multi_line_string &mls) {
+            return value::object_type{ { "type", "MultiLineString" },
+                                       { "coordinates", convert(mls) } };
+        },
+        [](const polygon &pol) {
+            return value::object_type{ { "type", "Polygon" }, { "coordinates", convert(pol) } };
+        },
+        [](const multi_polygon &mpol) {
+            return value::object_type{ { "type", "MultiPolygon" },
+                                       { "coordinates", convert(mpol) } };
+        },
+        [](const geometry_collection &gc) {
+            value::array_type geometries;
+            geometries.reserve(gc.size());
+            for (const auto &gcGeom : gc) {
+                geometries.push_back(convert(gcGeom));
+            }
+            return value::object_type{ { "type", "GeometryCollection" },
+                                       { "geometries", std::move(geometries) } };
+        });
+}
+
+value convert(const feature &f) {
+    value::object_type result{
+        { "type", "Feature" },
+        { "geometry", convert(f.geometry) },
+        { "properties", f.properties }
+    };
+
+    if (!f.id.is<mapbox::geojson::null_value_t>()) {
+        value id = f.id.match(
+            [](uint64_t n) -> value { return n; }, [](int64_t n) -> value { return n; },
+            [](double n) -> value { return n; }, [](std::string s) -> value { return s; },
+            [](const auto &) -> value { throw error("Unknown type for a Feature 'id'"); });
+        result.emplace(std::make_pair("id", std::move(id)));
+    }
+
+    return result;
+}
+
+value convert(const feature_collection &collection) {
+    value::object_type result{ { "type", "FeatureCollection" } };
+    value::array_type features;
+    features.reserve(collection.size());
+    for (const auto &feat : collection) {
+        features.emplace_back(convert(feat));
+    }
+    result.emplace(std::make_pair("features", std::move(features)));
+    return result;
+}
+
+value convert(const geojson &json) {
+    return json.match([](const geometry &g) { return convert(g); },
+                      [](const feature &f) { return convert(f); },
+                      [](const feature_collection &c) { return convert(c); });
+}
+
+} // namespace geojson
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt.hpp
deleted file mode 100644
index af5bbc312..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt.hpp
+++ /dev/null
@@ -1,254 +0,0 @@
-#pragma once
-
-#include <mapbox/geojsonvt/convert.hpp>
-#include <mapbox/geojsonvt/tile.hpp>
-#include <mapbox/geojsonvt/types.hpp>
-#include <mapbox/geojsonvt/wrap.hpp>
-
-#include <chrono>
-#include <cmath>
-#include <map>
-#include <unordered_map>
-
-namespace mapbox {
-namespace geojsonvt {
-
-using geometry = mapbox::geometry::geometry<double>;
-using feature = mapbox::geometry::feature<double>;
-using feature_collection = mapbox::geometry::feature_collection<double>;
-using geometry_collection = mapbox::geometry::geometry_collection<double>;
-using geojson = mapbox::util::variant<geometry, feature, feature_collection>;
-
-struct ToFeatureCollection {
-    feature_collection operator()(const feature_collection& value) const {
-        return value;
-    }
-    feature_collection operator()(const feature& value) const {
-        return { value };
-    }
-    feature_collection operator()(const geometry& value) const {
-        return { { value } };
-    }
-};
-
-struct TileOptions {
-    // simplification tolerance (higher means simpler)
-    double tolerance = 3;
-
-    // tile extent
-    uint16_t extent = 4096;
-
-    // tile buffer on each side
-    uint16_t buffer = 64;
-};
-
-struct Options : TileOptions {
-    // max zoom to preserve detail on
-    uint8_t maxZoom = 18;
-
-    // max zoom in the tile index
-    uint8_t indexMaxZoom = 5;
-
-    // max number of points per tile in the tile index
-    uint32_t indexMaxPoints = 100000;
-};
-
-const Tile empty_tile{};
-
-inline uint64_t toID(uint8_t z, uint32_t x, uint32_t y) {
-    return (((1ull << z) * y + x) * 32) + z;
-}
-
-inline const Tile geoJSONToTile(const geojson& geojson_,
-                                uint8_t z,
-                                uint32_t x,
-                                uint32_t y,
-                                const TileOptions& options = TileOptions(),
-                                bool wrap = false,
-                                bool clip = false) {
-
-    const auto features_ = geojson::visit(geojson_, ToFeatureCollection{});
-    auto z2 = 1u << z;
-    auto tolerance = (options.tolerance / options.extent) / z2;
-    auto features = detail::convert(features_, tolerance);
-    if (wrap) {
-        features = detail::wrap(features, double(options.buffer) / options.extent);
-    }
-    if (clip) {
-        const double p = options.buffer / options.extent;
-
-        const auto left = detail::clip<0>(features, (x - p) / z2, (x + 1 + p) / z2, -1, 2);
-        features = detail::clip<1>(left, (y - p) / z2, (y + 1 + p) / z2, -1, 2);
-    }
-    return detail::InternalTile({ features, z, x, y, options.extent, tolerance }).tile;
-}
-
-class GeoJSONVT {
-public:
-    const Options options;
-
-    GeoJSONVT(const mapbox::geometry::feature_collection<double>& features_,
-              const Options& options_ = Options())
-        : options(options_) {
-
-        const uint32_t z2 = 1u << options.maxZoom;
-
-        auto converted = detail::convert(features_, (options.tolerance / options.extent) / z2);
-        auto features = detail::wrap(converted, double(options.buffer) / options.extent);
-
-        splitTile(features, 0, 0, 0);
-    }
-
-    GeoJSONVT(const geojson& geojson_, const Options& options_ = Options())
-        : GeoJSONVT(geojson::visit(geojson_, ToFeatureCollection{}), options_) {
-    }
-
-    std::map<uint8_t, uint32_t> stats;
-    uint32_t total = 0;
-
-    const Tile& getTile(const uint8_t z, const uint32_t x_, const uint32_t y) {
-
-        if (z > options.maxZoom)
-            throw std::runtime_error("Requested zoom higher than maxZoom: " + std::to_string(z));
-
-        const uint32_t z2 = 1u << z;
-        const uint32_t x = ((x_ % z2) + z2) % z2; // wrap tile x coordinate
-        const uint64_t id = toID(z, x, y);
-
-        auto it = tiles.find(id);
-        if (it != tiles.end())
-            return it->second.tile;
-
-        it = findParent(z, x, y);
-
-        if (it == tiles.end())
-            throw std::runtime_error("Parent tile not found");
-
-        // if we found a parent tile containing the original geometry, we can drill down from it
-        const auto& parent = it->second;
-
-        // drill down parent tile up to the requested one
-        splitTile(parent.source_features, parent.z, parent.x, parent.y, z, x, y);
-
-        it = tiles.find(id);
-        if (it != tiles.end())
-            return it->second.tile;
-
-        it = findParent(z, x, y);
-        if (it == tiles.end())
-            throw std::runtime_error("Parent tile not found");
-
-        return empty_tile;
-    }
-
-    const std::unordered_map<uint64_t, detail::InternalTile>& getInternalTiles() const {
-        return tiles;
-    }
-
-private:
-    std::unordered_map<uint64_t, detail::InternalTile> tiles;
-
-    std::unordered_map<uint64_t, detail::InternalTile>::iterator
-    findParent(const uint8_t z, const uint32_t x, const uint32_t y) {
-        uint8_t z0 = z;
-        uint32_t x0 = x;
-        uint32_t y0 = y;
-
-        const auto end = tiles.end();
-        auto parent = end;
-
-        while ((parent == end) && (z0 != 0)) {
-            z0--;
-            x0 = x0 / 2;
-            y0 = y0 / 2;
-            parent = tiles.find(toID(z0, x0, y0));
-        }
-
-        return parent;
-    }
-
-    void splitTile(const detail::vt_features& features,
-                   const uint8_t z,
-                   const uint32_t x,
-                   const uint32_t y,
-                   const uint8_t cz = 0,
-                   const uint32_t cx = 0,
-                   const uint32_t cy = 0) {
-
-        const double z2 = 1u << z;
-        const uint64_t id = toID(z, x, y);
-
-        auto it = tiles.find(id);
-
-        if (it == tiles.end()) {
-            const double tolerance =
-                (z == options.maxZoom ? 0 : options.tolerance / (z2 * options.extent));
-
-            it = tiles
-                     .emplace(id,
-                              detail::InternalTile{ features, z, x, y, options.extent, tolerance })
-                     .first;
-            stats[z] = (stats.count(z) ? stats[z] + 1 : 1);
-            total++;
-            // printf("tile z%i-%i-%i\n", z, x, y);
-        }
-
-        auto& tile = it->second;
-
-        if (features.empty())
-            return;
-
-        // if it's the first-pass tiling
-        if (cz == 0u) {
-            // stop tiling if we reached max zoom, or if the tile is too simple
-            if (z == options.indexMaxZoom || tile.tile.num_points <= options.indexMaxPoints) {
-                tile.source_features = features;
-                return;
-            }
-
-        } else { // drilldown to a specific tile;
-            // stop tiling if we reached base zoom
-            if (z == options.maxZoom)
-                return;
-
-            // stop tiling if it's our target tile zoom
-            if (z == cz) {
-                tile.source_features = features;
-                return;
-            }
-
-            // stop tiling if it's not an ancestor of the target tile
-            const double m = 1u << (cz - z);
-            if (x != static_cast<uint32_t>(std::floor(cx / m)) ||
-                y != static_cast<uint32_t>(std::floor(cy / m))) {
-                tile.source_features = features;
-                return;
-            }
-        }
-
-        const double p = 0.5 * options.buffer / options.extent;
-        const auto& min = tile.bbox.min;
-        const auto& max = tile.bbox.max;
-
-        const auto left = detail::clip<0>(features, (x - p) / z2, (x + 0.5 + p) / z2, min.x, max.x);
-
-        splitTile(detail::clip<1>(left, (y - p) / z2, (y + 0.5 + p) / z2, min.y, max.y), z + 1,
-                  x * 2, y * 2, cz, cx, cy);
-        splitTile(detail::clip<1>(left, (y + 0.5 - p) / z2, (y + 1 + p) / z2, min.y, max.y), z + 1,
-                  x * 2, y * 2 + 1, cz, cx, cy);
-
-        const auto right =
-            detail::clip<0>(features, (x + 0.5 - p) / z2, (x + 1 + p) / z2, min.x, max.x);
-
-        splitTile(detail::clip<1>(right, (y - p) / z2, (y + 0.5 + p) / z2, min.y, max.y), z + 1,
-                  x * 2 + 1, y * 2, cz, cx, cy);
-        splitTile(detail::clip<1>(right, (y + 0.5 - p) / z2, (y + 1 + p) / z2, min.y, max.y), z + 1,
-                  x * 2 + 1, y * 2 + 1, cz, cx, cy);
-
-        // if we sliced further down, no need to keep source geometry
-        tile.source_features = {};
-    }
-};
-
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/clip.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/clip.hpp
deleted file mode 100644
index e6f305921..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/clip.hpp
+++ /dev/null
@@ -1,251 +0,0 @@
-#pragma once
-
-#include <mapbox/geojsonvt/types.hpp>
-
-namespace mapbox {
-namespace geojsonvt {
-namespace detail {
-
-template <uint8_t I>
-class clipper {
-public:
-    const double k1;
-    const double k2;
-
-    vt_geometry operator()(const vt_point& point) const {
-        return point;
-    }
-
-    vt_geometry operator()(const vt_multi_point& points) const {
-        vt_multi_point part;
-        for (const auto& p : points) {
-            const double ak = get<I>(p);
-            if (ak >= k1 && ak <= k2)
-                part.push_back(p);
-        }
-        return part;
-    }
-
-    vt_geometry operator()(const vt_line_string& line) const {
-        vt_multi_line_string parts;
-        clipLine(line, parts);
-        if (parts.size() == 1)
-            return parts[0];
-        else
-            return parts;
-    }
-
-    vt_geometry operator()(const vt_multi_line_string& lines) const {
-        vt_multi_line_string parts;
-        for (const auto& line : lines) {
-            clipLine(line, parts);
-        }
-        if (parts.size() == 1)
-            return parts[0];
-        else
-            return parts;
-    }
-
-    vt_geometry operator()(const vt_polygon& polygon) const {
-        vt_polygon result;
-        for (const auto& ring : polygon) {
-            const auto new_ring = clipRing(ring);
-            if (!new_ring.empty())
-                result.push_back(new_ring);
-        }
-        return result;
-    }
-
-    vt_geometry operator()(const vt_multi_polygon& polygons) const {
-        vt_multi_polygon result;
-        for (const auto& polygon : polygons) {
-            vt_polygon p;
-            for (const auto& ring : polygon) {
-                const auto new_ring = clipRing(ring);
-                if (!new_ring.empty())
-                    p.push_back(new_ring);
-            }
-            if (!p.empty())
-                result.push_back(p);
-        }
-        return result;
-    }
-
-    vt_geometry operator()(const vt_geometry_collection& geometries) const {
-        vt_geometry_collection result;
-        for (const auto& geometry : geometries) {
-            vt_geometry::visit(geometry,
-                               [&](const auto& g) { result.push_back(this->operator()(g)); });
-        }
-        return result;
-    }
-
-private:
-    vt_line_string newSlice(vt_multi_line_string& parts, vt_line_string& slice, double dist) const {
-        if (!slice.empty()) {
-            slice.dist = dist;
-            parts.push_back(std::move(slice));
-        }
-        return {};
-    }
-
-    void clipLine(const vt_line_string& line, vt_multi_line_string& slices) const {
-
-        const double dist = line.dist;
-        const size_t len = line.size();
-
-        if (len < 2)
-            return;
-
-        vt_line_string slice;
-
-        for (size_t i = 0; i < (len - 1); ++i) {
-            const auto& a = line[i];
-            const auto& b = line[i + 1];
-            const double ak = get<I>(a);
-            const double bk = get<I>(b);
-
-            if (ak < k1) {
-                if (bk > k2) { // ---|-----|-->
-                    slice.push_back(intersect<I>(a, b, k1));
-                    slice.push_back(intersect<I>(a, b, k2));
-                    slice = newSlice(slices, slice, dist);
-
-                } else if (bk >= k1) { // ---|-->  |
-                    slice.push_back(intersect<I>(a, b, k1));
-                    if (i == len - 2)
-                        slice.push_back(b); // last point
-                }
-            } else if (ak >= k2) {
-                if (bk < k1) { // <--|-----|---
-                    slice.push_back(intersect<I>(a, b, k2));
-                    slice.push_back(intersect<I>(a, b, k1));
-                    slice = newSlice(slices, slice, dist);
-
-                } else if (bk < k2) { // |  <--|---
-                    slice.push_back(intersect<I>(a, b, k2));
-                    if (i == len - 2)
-                        slice.push_back(b); // last point
-                }
-            } else {
-                slice.push_back(a);
-
-                if (bk < k1) { // <--|---  |
-                    slice.push_back(intersect<I>(a, b, k1));
-                    slice = newSlice(slices, slice, dist);
-
-                } else if (bk > k2) { // |  ---|-->
-                    slice.push_back(intersect<I>(a, b, k2));
-                    slice = newSlice(slices, slice, dist);
-
-                } else if (i == len - 2) { // | --> |
-                    slice.push_back(b);
-                }
-            }
-        }
-
-        // add the final slice
-        newSlice(slices, slice, dist);
-    }
-
-    vt_linear_ring clipRing(const vt_linear_ring& ring) const {
-        const size_t len = ring.size();
-
-        vt_linear_ring slice;
-        slice.area = ring.area;
-
-        if (len < 2)
-            return slice;
-
-        for (size_t i = 0; i < (len - 1); ++i) {
-            const auto& a = ring[i];
-            const auto& b = ring[i + 1];
-            const double ak = get<I>(a);
-            const double bk = get<I>(b);
-
-            if (ak < k1) {
-                if (bk >= k1) {
-                    slice.push_back(intersect<I>(a, b, k1)); // ---|-->  |
-                    if (bk > k2)                             // ---|-----|-->
-                        slice.push_back(intersect<I>(a, b, k2));
-                    else if (i == len - 2)
-                        slice.push_back(b); // last point
-                }
-            } else if (ak >= k2) {
-                if (bk < k2) { // |  <--|---
-                    slice.push_back(intersect<I>(a, b, k2));
-                    if (bk < k1) // <--|-----|---
-                        slice.push_back(intersect<I>(a, b, k1));
-                    else if (i == len - 2)
-                        slice.push_back(b); // last point
-                }
-            } else {
-                slice.push_back(a);
-                if (bk < k1) // <--|---  |
-                    slice.push_back(intersect<I>(a, b, k1));
-                else if (bk > k2) // |  ---|-->
-                    slice.push_back(intersect<I>(a, b, k2));
-                // | --> |
-            }
-        }
-
-        // close the polygon if its endpoints are not the same after clipping
-        if (!slice.empty()) {
-            const auto& first = slice.front();
-            const auto& last = slice.back();
-            if (first != last) {
-                slice.push_back(first);
-            }
-        }
-
-        return slice;
-    }
-};
-
-/* clip features between two axis-parallel lines:
- *     |        |
- *  ___|___     |     /
- * /   |   \____|____/
- *     |        |
- */
-
-template <uint8_t I>
-inline vt_features clip(const vt_features& features,
-                        const double k1,
-                        const double k2,
-                        const double minAll,
-                        const double maxAll) {
-
-    if (minAll >= k1 && maxAll < k2) // trivial accept
-        return features;
-
-    if (maxAll < k1 || minAll >= k2) // trivial reject
-        return {};
-
-    vt_features clipped;
-
-    for (const auto& feature : features) {
-        const auto& geom = feature.geometry;
-        const auto& props = feature.properties;
-        const auto& id = feature.id;
-
-        const double min = get<I>(feature.bbox.min);
-        const double max = get<I>(feature.bbox.max);
-
-        if (min >= k1 && max < k2) { // trivial accept
-            clipped.push_back(feature);
-
-        } else if (max < k1 || min >= k2) { // trivial reject
-            continue;
-
-        } else {
-            clipped.emplace_back(vt_geometry::visit(geom, clipper<I>{ k1, k2 }), props, id);
-        }
-    }
-
-    return clipped;
-}
-
-} // namespace detail
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/convert.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/convert.hpp
deleted file mode 100644
index 88c036f02..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/convert.hpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#pragma once
-
-#include <mapbox/geojsonvt/simplify.hpp>
-#include <mapbox/geojsonvt/types.hpp>
-#include <mapbox/geometry.hpp>
-
-#include <algorithm>
-#include <cmath>
-
-namespace mapbox {
-namespace geojsonvt {
-namespace detail {
-
-struct project {
-    const double tolerance;
-    using result_type = vt_geometry;
-
-    vt_point operator()(const geometry::point<double>& p) {
-        const double sine = std::sin(p.y * M_PI / 180);
-        const double x = p.x / 360 + 0.5;
-        const double y =
-            std::max(std::min(0.5 - 0.25 * std::log((1 + sine) / (1 - sine)) / M_PI, 1.0), 0.0);
-        return { x, y, 0.0 };
-    }
-
-    vt_line_string operator()(const geometry::line_string<double>& points) {
-        vt_line_string result;
-        const size_t len = points.size();
-
-        if (len == 0)
-            return result;
-
-        result.reserve(len);
-
-        for (const auto& p : points) {
-            result.push_back(operator()(p));
-        }
-
-        for (size_t i = 0; i < len - 1; ++i) {
-            const auto& a = result[i];
-            const auto& b = result[i + 1];
-            // use Manhattan distance instead of Euclidian to avoid expensive square root
-            // computation
-            result.dist += std::abs(b.x - a.x) + std::abs(b.y - a.y);
-        }
-
-        simplify(result, tolerance);
-
-        return result;
-    }
-
-    vt_linear_ring operator()(const geometry::linear_ring<double>& ring) {
-        vt_linear_ring result;
-        const size_t len = ring.size();
-
-        if (len == 0)
-            return result;
-
-        result.reserve(len);
-
-        for (const auto& p : ring) {
-            result.push_back(operator()(p));
-        }
-
-        double area = 0.0;
-
-        for (size_t i = 0; i < len - 1; ++i) {
-            const auto& a = result[i];
-            const auto& b = result[i + 1];
-            area += a.x * b.y - b.x * a.y;
-        }
-        result.area = std::abs(area / 2);
-
-        simplify(result, tolerance);
-
-        return result;
-    }
-
-    vt_geometry operator()(const geometry::geometry<double>& geometry) {
-        return geometry::geometry<double>::visit(geometry, project{ tolerance });
-    }
-
-    // Handles polygon, multi_*, geometry_collection.
-    template <class T>
-    auto operator()(const T& vector) {
-        typename vt_geometry_type<T>::type result;
-        result.reserve(vector.size());
-        for (const auto& e : vector) {
-            result.push_back(operator()(e));
-        }
-        return result;
-    }
-};
-
-inline vt_features convert(const geometry::feature_collection<double>& features,
-                           const double tolerance) {
-    vt_features projected;
-    projected.reserve(features.size());
-    for (const auto& feature : features) {
-        projected.emplace_back(
-            geometry::geometry<double>::visit(feature.geometry, project{ tolerance }),
-            feature.properties, feature.id);
-    }
-    return projected;
-}
-
-} // namespace detail
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/simplify.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/simplify.hpp
deleted file mode 100644
index 784f085e7..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/simplify.hpp
+++ /dev/null
@@ -1,84 +0,0 @@
-#pragma once
-
-#include <mapbox/geojsonvt/types.hpp>
-
-namespace mapbox {
-namespace geojsonvt {
-namespace detail {
-
-// square distance from a point to a segment
-inline double getSqSegDist(const vt_point& p, const vt_point& a, const vt_point& b) {
-    double x = a.x;
-    double y = a.y;
-    double dx = b.x - a.x;
-    double dy = b.y - a.y;
-
-    if ((dx != 0.0) || (dy != 0.0)) {
-
-        const double t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy);
-
-        if (t > 1) {
-            x = b.x;
-            y = b.y;
-
-        } else if (t > 0) {
-            x += dx * t;
-            y += dy * t;
-        }
-    }
-
-    dx = p.x - x;
-    dy = p.y - y;
-
-    return dx * dx + dy * dy;
-}
-
-// calculate simplification data using optimized Douglas-Peucker algorithm
-inline void simplify(std::vector<vt_point>& points, size_t first, size_t last, double sqTolerance) {
-    double maxSqDist = sqTolerance;
-    size_t index = 0;
-    const int64_t mid = (last - first) >> 1;
-    int64_t minPosToMid = last - first;
-
-    for (auto i = first + 1; i < last; i++) {
-        const double sqDist = getSqSegDist(points[i], points[first], points[last]);
-
-        if (sqDist > maxSqDist) {
-            index = i;
-            maxSqDist = sqDist;
-
-        } else if (sqDist == maxSqDist) {
-            // a workaround to ensure we choose a pivot close to the middle of the list,
-            // reducing recursion depth, for certain degenerate inputs
-            // https://github.com/mapbox/geojson-vt/issues/104
-            auto posToMid = std::abs(static_cast<int64_t>(i) - mid);
-            if (posToMid < minPosToMid) {
-                index = i;
-                minPosToMid = posToMid;
-            }
-        }
-    }
-
-    if (maxSqDist > sqTolerance) {
-        // save the point importance in squared pixels as a z coordinate
-        points[index].z = maxSqDist;
-        if (index - first > 1)
-            simplify(points, first, index, sqTolerance);
-        if (last - index > 1)
-            simplify(points, index, last, sqTolerance);
-    }
-}
-
-inline void simplify(std::vector<vt_point>& points, double tolerance) {
-    const size_t len = points.size();
-
-    // always retain the endpoints (1 is the max value)
-    points[0].z = 1.0;
-    points[len - 1].z = 1.0;
-
-    simplify(points, 0, len - 1, tolerance * tolerance);
-}
-
-} // namespace detail
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/tile.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/tile.hpp
deleted file mode 100644
index e38234677..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/tile.hpp
+++ /dev/null
@@ -1,184 +0,0 @@
-#pragma once
-
-#include <algorithm>
-#include <cmath>
-#include <mapbox/geojsonvt/types.hpp>
-
-namespace mapbox {
-namespace geojsonvt {
-
-struct Tile {
-    mapbox::geometry::feature_collection<int16_t> features;
-    uint32_t num_points = 0;
-    uint32_t num_simplified = 0;
-};
-
-namespace detail {
-
-class InternalTile {
-public:
-    const uint16_t extent;
-    const uint8_t z;
-    const uint32_t x;
-    const uint32_t y;
-
-    const double z2;
-    const double tolerance;
-    const double sq_tolerance;
-
-    vt_features source_features;
-    mapbox::geometry::box<double> bbox = { { 2, 1 }, { -1, 0 } };
-
-    Tile tile;
-
-    InternalTile(const vt_features& source,
-                 const uint8_t z_,
-                 const uint32_t x_,
-                 const uint32_t y_,
-                 const uint16_t extent_,
-                 const double tolerance_)
-        : extent(extent_),
-          z(z_),
-          x(x_),
-          y(y_),
-          z2(std::pow(2, z)),
-          tolerance(tolerance_),
-          sq_tolerance(tolerance_ * tolerance_) {
-
-        for (const auto& feature : source) {
-            const auto& geom = feature.geometry;
-            const auto& props = feature.properties;
-            const auto& id = feature.id;
-
-            tile.num_points += feature.num_points;
-
-            vt_geometry::visit(geom, [&](const auto& g) {
-                // `this->` is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636
-                this->addFeature(g, props, id);
-            });
-
-            bbox.min.x = std::min(feature.bbox.min.x, bbox.min.x);
-            bbox.min.y = std::min(feature.bbox.min.y, bbox.min.y);
-            bbox.max.x = std::max(feature.bbox.max.x, bbox.max.x);
-            bbox.max.y = std::max(feature.bbox.max.y, bbox.max.y);
-        }
-    }
-
-private:
-    void
-    addFeature(const vt_point& point, const property_map& props, const optional<identifier>& id) {
-        tile.features.push_back({ transform(point), props, id });
-    }
-
-    void addFeature(const vt_line_string& line,
-                    const property_map& props,
-                    const optional<identifier>& id) {
-        const auto new_line = transform(line);
-        if (!new_line.empty())
-            tile.features.push_back({ std::move(new_line), props, id });
-    }
-
-    void addFeature(const vt_polygon& polygon,
-                    const property_map& props,
-                    const optional<identifier>& id) {
-        const auto new_polygon = transform(polygon);
-        if (!new_polygon.empty())
-            tile.features.push_back({ std::move(new_polygon), props, id });
-    }
-
-    void addFeature(const vt_geometry_collection& collection,
-                    const property_map& props,
-                    const optional<identifier>& id) {
-        for (const auto& geom : collection) {
-            vt_geometry::visit(geom, [&](const auto& g) {
-                // `this->` is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636
-                this->addFeature(g, props, id);
-            });
-        }
-    }
-
-    template <class T>
-    void addFeature(const T& multi, const property_map& props, const optional<identifier>& id) {
-        const auto new_multi = transform(multi);
-
-        switch (new_multi.size()) {
-        case 0:
-            break;
-        case 1:
-            tile.features.push_back({ std::move(new_multi[0]), props, id });
-            break;
-        default:
-            tile.features.push_back({ std::move(new_multi), props, id });
-            break;
-        }
-    }
-
-    mapbox::geometry::point<int16_t> transform(const vt_point& p) {
-        ++tile.num_simplified;
-        return { static_cast<int16_t>(::round((p.x * z2 - x) * extent)),
-                 static_cast<int16_t>(::round((p.y * z2 - y) * extent)) };
-    }
-
-    mapbox::geometry::multi_point<int16_t> transform(const vt_multi_point& points) {
-        mapbox::geometry::multi_point<int16_t> result;
-        result.reserve(points.size());
-        for (const auto& p : points) {
-            result.push_back(transform(p));
-        }
-        return result;
-    }
-
-    mapbox::geometry::line_string<int16_t> transform(const vt_line_string& line) {
-        mapbox::geometry::line_string<int16_t> result;
-        if (line.dist > tolerance) {
-            for (const auto& p : line) {
-                if (p.z > sq_tolerance)
-                    result.push_back(transform(p));
-            }
-        }
-        return result;
-    }
-
-    mapbox::geometry::linear_ring<int16_t> transform(const vt_linear_ring& ring) {
-        mapbox::geometry::linear_ring<int16_t> result;
-        if (ring.area > sq_tolerance) {
-            for (const auto& p : ring) {
-                if (p.z > sq_tolerance)
-                    result.push_back(transform(p));
-            }
-        }
-        return result;
-    }
-
-    mapbox::geometry::multi_line_string<int16_t> transform(const vt_multi_line_string& lines) {
-        mapbox::geometry::multi_line_string<int16_t> result;
-        for (const auto& line : lines) {
-            if (line.dist > tolerance)
-                result.push_back(transform(line));
-        }
-        return result;
-    }
-
-    mapbox::geometry::polygon<int16_t> transform(const vt_polygon& rings) {
-        mapbox::geometry::polygon<int16_t> result;
-        for (const auto& ring : rings) {
-            if (ring.area > sq_tolerance)
-                result.push_back(transform(ring));
-        }
-        return result;
-    }
-
-    mapbox::geometry::multi_polygon<int16_t> transform(const vt_multi_polygon& polygons) {
-        mapbox::geometry::multi_polygon<int16_t> result;
-        for (const auto& polygon : polygons) {
-            const auto p = transform(polygon);
-            if (!p.empty())
-                result.push_back(std::move(p));
-        }
-        return result;
-    }
-};
-
-} // namespace detail
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/types.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/types.hpp
deleted file mode 100644
index b65844f43..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/types.hpp
+++ /dev/null
@@ -1,162 +0,0 @@
-#pragma once
-
-#include <mapbox/geometry.hpp>
-#include <mapbox/variant.hpp>
-
-#include <algorithm>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-namespace mapbox {
-namespace geojsonvt {
-namespace detail {
-
-struct vt_point : mapbox::geometry::point<double> {
-    double z = 0.0; // simplification tolerance
-
-    vt_point(double x_, double y_, double z_) : mapbox::geometry::point<double>(x_, y_), z(z_) {
-    }
-
-    vt_point(double x_, double y_) : vt_point(x_, y_, 0.0) {
-    }
-};
-
-template <uint8_t I, typename T>
-inline double get(const T&);
-
-template <>
-inline double get<0>(const vt_point& p) {
-    return p.x;
-}
-template <>
-inline double get<1>(const vt_point& p) {
-    return p.y;
-}
-template <>
-inline double get<0>(const mapbox::geometry::point<double>& p) {
-    return p.x;
-}
-template <>
-inline double get<1>(const mapbox::geometry::point<double>& p) {
-    return p.y;
-}
-
-template <uint8_t I>
-inline vt_point intersect(const vt_point&, const vt_point&, const double);
-
-template <>
-inline vt_point intersect<0>(const vt_point& a, const vt_point& b, const double x) {
-    const double y = (x - a.x) * (b.y - a.y) / (b.x - a.x) + a.y;
-    return { x, y, 1.0 };
-}
-template <>
-inline vt_point intersect<1>(const vt_point& a, const vt_point& b, const double y) {
-    const double x = (y - a.y) * (b.x - a.x) / (b.y - a.y) + a.x;
-    return { x, y, 1.0 };
-}
-
-using vt_multi_point = std::vector<vt_point>;
-
-struct vt_line_string : std::vector<vt_point> {
-    using container_type = std::vector<vt_point>;
-    vt_line_string() = default;
-    vt_line_string(std::initializer_list<vt_point> args)
-      : container_type(std::move(args)) {}
-
-    double dist = 0.0; // line length
-};
-
-struct vt_linear_ring : std::vector<vt_point> {
-    using container_type = std::vector<vt_point>;
-    vt_linear_ring() = default;
-    vt_linear_ring(std::initializer_list<vt_point> args)
-      : container_type(std::move(args)) {}
-
-    double area = 0.0; // polygon ring area
-};
-
-using vt_multi_line_string = std::vector<vt_line_string>;
-using vt_polygon = std::vector<vt_linear_ring>;
-using vt_multi_polygon = std::vector<vt_polygon>;
-
-struct vt_geometry_collection;
-
-using vt_geometry = mapbox::util::variant<vt_point,
-                                          vt_line_string,
-                                          vt_polygon,
-                                          vt_multi_point,
-                                          vt_multi_line_string,
-                                          vt_multi_polygon,
-                                          vt_geometry_collection>;
-
-struct vt_geometry_collection : std::vector<vt_geometry> {};
-
-using property_map = mapbox::geometry::property_map;
-using identifier = mapbox::geometry::identifier;
-
-template <class T>
-using optional = std::experimental::optional<T>;
-
-template <class T>
-struct vt_geometry_type;
-
-template <>
-struct vt_geometry_type<geometry::point<double>> {
-    using type = vt_point;
-};
-template <>
-struct vt_geometry_type<geometry::line_string<double>> {
-    using type = vt_line_string;
-};
-template <>
-struct vt_geometry_type<geometry::polygon<double>> {
-    using type = vt_polygon;
-};
-template <>
-struct vt_geometry_type<geometry::multi_point<double>> {
-    using type = vt_multi_point;
-};
-template <>
-struct vt_geometry_type<geometry::multi_line_string<double>> {
-    using type = vt_multi_line_string;
-};
-template <>
-struct vt_geometry_type<geometry::multi_polygon<double>> {
-    using type = vt_multi_polygon;
-};
-template <>
-struct vt_geometry_type<geometry::geometry<double>> {
-    using type = vt_geometry;
-};
-template <>
-struct vt_geometry_type<geometry::geometry_collection<double>> {
-    using type = vt_geometry_collection;
-};
-
-struct vt_feature {
-    vt_geometry geometry;
-    property_map properties;
-    optional<identifier> id;
-
-    mapbox::geometry::box<double> bbox = { { 2, 1 }, { -1, 0 } };
-    uint32_t num_points = 0;
-
-    vt_feature(const vt_geometry& geom, const property_map& props, const optional<identifier>& id_)
-        : geometry(geom), properties(props), id(id_) {
-
-        mapbox::geometry::for_each_point(geom, [&](const vt_point& p) {
-            bbox.min.x = std::min(p.x, bbox.min.x);
-            bbox.min.y = std::min(p.y, bbox.min.y);
-            bbox.max.x = std::max(p.x, bbox.max.x);
-            bbox.max.y = std::max(p.y, bbox.max.y);
-            ++num_points;
-        });
-    }
-};
-
-using vt_features = std::vector<vt_feature>;
-
-} // namespace detail
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/wrap.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/wrap.hpp
deleted file mode 100644
index 495ccc580..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.5.1/include/mapbox/geojsonvt/wrap.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-
-#include <mapbox/geojsonvt/clip.hpp>
-#include <mapbox/geojsonvt/types.hpp>
-
-namespace mapbox {
-namespace geojsonvt {
-namespace detail {
-
-inline void shiftCoords(vt_features& features, double offset) {
-    for (auto& feature : features) {
-        mapbox::geometry::for_each_point(feature.geometry,
-                                         [offset](vt_point& point) { point.x += offset; });
-        feature.bbox.min.x += offset;
-        feature.bbox.max.x += offset;
-    }
-}
-
-inline vt_features wrap(const vt_features& features, double buffer) {
-    // left world copy
-    auto left = clip<0>(features, -1 - buffer, buffer, -1, 2);
-    // right world copy
-    auto right = clip<0>(features, 1 - buffer, 2 + buffer, -1, 2);
-
-    if (left.empty() && right.empty())
-        return features;
-
-    // center world copy
-    auto merged = clip<0>(features, -buffer, 1 + buffer, -1, 2);
-
-    if (!left.empty()) {
-        // merge left into center
-        shiftCoords(left, 1.0);
-        merged.insert(merged.begin(), left.begin(), left.end());
-    }
-    if (!right.empty()) {
-        // merge right into center
-        shiftCoords(right, -1.0);
-        merged.insert(merged.end(), right.begin(), right.end());
-    }
-    return merged;
-}
-
-} // namespace detail
-} // namespace geojsonvt
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt.hpp
new file mode 100644
index 000000000..80ac43265
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt.hpp
@@ -0,0 +1,262 @@
+#pragma once
+
+#include <mapbox/geojsonvt/convert.hpp>
+#include <mapbox/geojsonvt/tile.hpp>
+#include <mapbox/geojsonvt/types.hpp>
+#include <mapbox/geojsonvt/wrap.hpp>
+
+#include <mapbox/feature.hpp>
+
+#include <chrono>
+#include <cmath>
+#include <map>
+#include <unordered_map>
+
+namespace mapbox {
+namespace geojsonvt {
+
+using geometry = mapbox::geometry::geometry<double>;
+using feature = mapbox::feature::feature<double>;
+using feature_collection = mapbox::feature::feature_collection<double>;
+using geometry_collection = mapbox::geometry::geometry_collection<double>;
+using geojson = mapbox::util::variant<geometry, feature, feature_collection>;
+
+struct ToFeatureCollection {
+    feature_collection operator()(const feature_collection& value) const {
+        return value;
+    }
+    feature_collection operator()(const feature& value) const {
+        return { value };
+    }
+    feature_collection operator()(const geometry& value) const {
+        return { { value } };
+    }
+};
+
+struct TileOptions {
+    // simplification tolerance (higher means simpler)
+    double tolerance = 3;
+
+    // tile extent
+    uint16_t extent = 4096;
+
+    // tile buffer on each side
+    uint16_t buffer = 64;
+
+    // enable line metrics tracking for LineString/MultiLineString features
+    bool lineMetrics = false;
+};
+
+struct Options : TileOptions {
+    // max zoom to preserve detail on
+    uint8_t maxZoom = 18;
+
+    // max zoom in the tile index
+    uint8_t indexMaxZoom = 5;
+
+    // max number of points per tile in the tile index
+    uint32_t indexMaxPoints = 100000;
+
+    // whether to generate feature ids, overriding existing ids  
+    bool generateId = false;
+};
+
+const Tile empty_tile{};
+
+inline uint64_t toID(uint8_t z, uint32_t x, uint32_t y) {
+    return (((1ull << z) * y + x) * 32) + z;
+}
+
+inline const Tile geoJSONToTile(const geojson& geojson_,
+                                uint8_t z,
+                                uint32_t x,
+                                uint32_t y,
+                                const TileOptions& options = TileOptions(),
+                                bool wrap = false,
+                                bool clip = false) {
+
+    const auto features_ = geojson::visit(geojson_, ToFeatureCollection{});
+    auto z2 = 1u << z;
+    auto tolerance = (options.tolerance / options.extent) / z2;
+    auto features = detail::convert(features_, tolerance, false);
+    if (wrap) {
+        features = detail::wrap(features, double(options.buffer) / options.extent, options.lineMetrics);
+    }
+    if (clip || options.lineMetrics) {
+        const double p = double(options.buffer) / options.extent;
+
+        const auto left = detail::clip<0>(features, (x - p) / z2, (x + 1 + p) / z2, -1, 2, options.lineMetrics);
+        features = detail::clip<1>(left, (y - p) / z2, (y + 1 + p) / z2, -1, 2, options.lineMetrics);
+    }
+    return detail::InternalTile({ features, z, x, y, options.extent, tolerance, options.lineMetrics }).tile;
+}
+
+class GeoJSONVT {
+public:
+    const Options options;
+
+    GeoJSONVT(const mapbox::feature::feature_collection<double>& features_,
+              const Options& options_ = Options())
+        : options(options_) {
+
+        const uint32_t z2 = 1u << options.maxZoom;
+
+        auto converted = detail::convert(features_, (options.tolerance / options.extent) / z2, options.generateId);
+        auto features = detail::wrap(converted, double(options.buffer) / options.extent, options.lineMetrics);
+
+        splitTile(features, 0, 0, 0);
+    }
+
+    GeoJSONVT(const geojson& geojson_, const Options& options_ = Options())
+        : GeoJSONVT(geojson::visit(geojson_, ToFeatureCollection{}), options_) {
+    }
+
+    std::map<uint8_t, uint32_t> stats;
+    uint32_t total = 0;
+
+    const Tile& getTile(const uint8_t z, const uint32_t x_, const uint32_t y) {
+
+        if (z > options.maxZoom)
+            throw std::runtime_error("Requested zoom higher than maxZoom: " + std::to_string(z));
+
+        const uint32_t z2 = 1u << z;
+        const uint32_t x = ((x_ % z2) + z2) % z2; // wrap tile x coordinate
+        const uint64_t id = toID(z, x, y);
+
+        auto it = tiles.find(id);
+        if (it != tiles.end())
+            return it->second.tile;
+
+        it = findParent(z, x, y);
+
+        if (it == tiles.end())
+            throw std::runtime_error("Parent tile not found");
+
+        // if we found a parent tile containing the original geometry, we can drill down from it
+        const auto& parent = it->second;
+
+        // drill down parent tile up to the requested one
+        splitTile(parent.source_features, parent.z, parent.x, parent.y, z, x, y);
+
+        it = tiles.find(id);
+        if (it != tiles.end())
+            return it->second.tile;
+
+        it = findParent(z, x, y);
+        if (it == tiles.end())
+            throw std::runtime_error("Parent tile not found");
+
+        return empty_tile;
+    }
+
+    const std::unordered_map<uint64_t, detail::InternalTile>& getInternalTiles() const {
+        return tiles;
+    }
+
+private:
+    std::unordered_map<uint64_t, detail::InternalTile> tiles;
+
+    std::unordered_map<uint64_t, detail::InternalTile>::iterator
+    findParent(const uint8_t z, const uint32_t x, const uint32_t y) {
+        uint8_t z0 = z;
+        uint32_t x0 = x;
+        uint32_t y0 = y;
+
+        const auto end = tiles.end();
+        auto parent = end;
+
+        while ((parent == end) && (z0 != 0)) {
+            z0--;
+            x0 = x0 / 2;
+            y0 = y0 / 2;
+            parent = tiles.find(toID(z0, x0, y0));
+        }
+
+        return parent;
+    }
+
+    void splitTile(const detail::vt_features& features,
+                   const uint8_t z,
+                   const uint32_t x,
+                   const uint32_t y,
+                   const uint8_t cz = 0,
+                   const uint32_t cx = 0,
+                   const uint32_t cy = 0) {
+
+        const double z2 = 1u << z;
+        const uint64_t id = toID(z, x, y);
+
+        auto it = tiles.find(id);
+
+        if (it == tiles.end()) {
+            const double tolerance =
+                (z == options.maxZoom ? 0 : options.tolerance / (z2 * options.extent));
+
+            it = tiles
+                     .emplace(id,
+                              detail::InternalTile{ features, z, x, y, options.extent, tolerance, options.lineMetrics })
+                     .first;
+            stats[z] = (stats.count(z) ? stats[z] + 1 : 1);
+            total++;
+            // printf("tile z%i-%i-%i\n", z, x, y);
+        }
+
+        auto& tile = it->second;
+
+        if (features.empty())
+            return;
+
+        // if it's the first-pass tiling
+        if (cz == 0u) {
+            // stop tiling if we reached max zoom, or if the tile is too simple
+            if (z == options.indexMaxZoom || tile.tile.num_points <= options.indexMaxPoints) {
+                tile.source_features = features;
+                return;
+            }
+
+        } else { // drilldown to a specific tile;
+            // stop tiling if we reached base zoom
+            if (z == options.maxZoom)
+                return;
+
+            // stop tiling if it's our target tile zoom
+            if (z == cz) {
+                tile.source_features = features;
+                return;
+            }
+
+            // stop tiling if it's not an ancestor of the target tile
+            const double m = 1u << (cz - z);
+            if (x != static_cast<uint32_t>(std::floor(cx / m)) ||
+                y != static_cast<uint32_t>(std::floor(cy / m))) {
+                tile.source_features = features;
+                return;
+            }
+        }
+
+        const double p = 0.5 * options.buffer / options.extent;
+        const auto& min = tile.bbox.min;
+        const auto& max = tile.bbox.max;
+
+        const auto left = detail::clip<0>(features, (x - p) / z2, (x + 0.5 + p) / z2, min.x, max.x, options.lineMetrics);
+
+        splitTile(detail::clip<1>(left, (y - p) / z2, (y + 0.5 + p) / z2, min.y, max.y, options.lineMetrics), z + 1,
+                  x * 2, y * 2, cz, cx, cy);
+        splitTile(detail::clip<1>(left, (y + 0.5 - p) / z2, (y + 1 + p) / z2, min.y, max.y, options.lineMetrics), z + 1,
+                  x * 2, y * 2 + 1, cz, cx, cy);
+
+        const auto right =
+            detail::clip<0>(features, (x + 0.5 - p) / z2, (x + 1 + p) / z2, min.x, max.x, options.lineMetrics);
+
+        splitTile(detail::clip<1>(right, (y - p) / z2, (y + 0.5 + p) / z2, min.y, max.y, options.lineMetrics), z + 1,
+                  x * 2 + 1, y * 2, cz, cx, cy);
+        splitTile(detail::clip<1>(right, (y + 0.5 - p) / z2, (y + 1 + p) / z2, min.y, max.y, options.lineMetrics), z + 1,
+                  x * 2 + 1, y * 2 + 1, cz, cx, cy);
+
+        // if we sliced further down, no need to keep source geometry
+        tile.source_features = {};
+    }
+};
+
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/clip.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/clip.hpp
new file mode 100644
index 000000000..881ef1655
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/clip.hpp
@@ -0,0 +1,321 @@
+#pragma once
+
+#include <mapbox/geojsonvt/types.hpp>
+
+namespace mapbox {
+namespace geojsonvt {
+namespace detail {
+
+template <uint8_t I>
+class clipper {
+public:
+    clipper(double k1_, double k2_, bool lineMetrics_ = false)
+        : k1(k1_), k2(k2_), lineMetrics(lineMetrics_) {}
+
+    const double k1;
+    const double k2;
+    const bool lineMetrics;
+
+    vt_geometry operator()(const vt_empty& empty) const {
+        return empty;
+    }
+
+    vt_geometry operator()(const vt_point& point) const {
+        return point;
+    }
+
+    vt_geometry operator()(const vt_multi_point& points) const {
+        vt_multi_point part;
+        for (const auto& p : points) {
+            const double ak = get<I>(p);
+            if (ak >= k1 && ak <= k2)
+                part.emplace_back(p);
+        }
+        return part;
+    }
+
+    vt_geometry operator()(const vt_line_string& line) const {
+        vt_multi_line_string parts;
+        clipLine(line, parts);
+        if (parts.size() == 1)
+            return parts[0];
+        else
+            return parts;
+    }
+
+    vt_geometry operator()(const vt_multi_line_string& lines) const {
+        vt_multi_line_string parts;
+        for (const auto& line : lines) {
+            clipLine(line, parts);
+        }
+        if (parts.size() == 1)
+            return parts[0];
+        else
+            return parts;
+    }
+
+    vt_geometry operator()(const vt_polygon& polygon) const {
+        vt_polygon result;
+        for (const auto& ring : polygon) {
+            auto new_ring = clipRing(ring);
+            if (!new_ring.empty())
+                result.emplace_back(std::move(new_ring));
+        }
+        return result;
+    }
+
+    vt_geometry operator()(const vt_multi_polygon& polygons) const {
+        vt_multi_polygon result;
+        for (const auto& polygon : polygons) {
+            vt_polygon p;
+            for (const auto& ring : polygon) {
+                auto new_ring = clipRing(ring);
+                if (!new_ring.empty())
+                    p.emplace_back(std::move(new_ring));
+            }
+            if (!p.empty())
+                result.emplace_back(std::move(p));
+        }
+        return result;
+    }
+
+    vt_geometry operator()(const vt_geometry_collection& geometries) const {
+        vt_geometry_collection result;
+        for (const auto& geometry : geometries) {
+            vt_geometry::visit(geometry,
+                               [&](const auto& g) { result.emplace_back(this->operator()(g)); });
+        }
+        return result;
+    }
+
+private:
+    vt_line_string newSlice(const vt_line_string& line) const {
+        vt_line_string slice;
+        slice.dist = line.dist;
+        if (lineMetrics) {
+            slice.segStart = line.segStart;
+            slice.segEnd = line.segEnd;
+        }
+        return slice;
+    }
+
+    void clipLine(const vt_line_string& line, vt_multi_line_string& slices) const {
+        const size_t len = line.size();
+        double lineLen = line.segStart;
+        double segLen = 0.0;
+        double t = 0.0;
+
+        if (len < 2)
+            return;
+
+        vt_line_string slice = newSlice(line);
+
+        for (size_t i = 0; i < (len - 1); ++i) {
+            const auto& a = line[i];
+            const auto& b = line[i + 1];
+            const double ak = get<I>(a);
+            const double bk = get<I>(b);
+            const bool isLastSeg = (i == (len - 2));
+
+            if (lineMetrics) segLen = ::hypot((b.x - a.x), (b.y - a.y));
+
+            if (ak < k1) {
+                if (bk > k2) { // ---|-----|-->
+                    t = calc_progress<I>(a, b, k1);
+                    slice.emplace_back(intersect<I>(a, b, k1, t));
+                    if (lineMetrics) slice.segStart = lineLen + segLen * t;
+
+                    t = calc_progress<I>(a, b, k2);
+                    slice.emplace_back(intersect<I>(a, b, k2, t));
+                    if (lineMetrics) slice.segEnd = lineLen + segLen * t;
+                    slices.emplace_back(std::move(slice));
+
+                    slice = newSlice(line);
+
+                } else if (bk > k1) { // ---|-->  |
+                    t = calc_progress<I>(a, b, k1);
+                    slice.emplace_back(intersect<I>(a, b, k1, t));
+                    if (lineMetrics) slice.segStart = lineLen + segLen * t;
+                    if (isLastSeg) slice.emplace_back(b); // last point
+
+                } else if (bk == k1 && !isLastSeg) { // --->|..  |
+                    if (lineMetrics) slice.segStart = lineLen + segLen;
+                    slice.emplace_back(b);
+                }
+            } else if (ak > k2) {
+                if (bk < k1) { // <--|-----|---
+                    t = calc_progress<I>(a, b, k2);
+                    slice.emplace_back(intersect<I>(a, b, k2, t));
+                    if (lineMetrics) slice.segStart = lineLen + segLen * t;
+
+                    t = calc_progress<I>(a, b, k1);
+                    slice.emplace_back(intersect<I>(a, b, k1, t));
+                    if (lineMetrics) slice.segEnd = lineLen + segLen * t;
+
+                    slices.emplace_back(std::move(slice));
+
+                    slice = newSlice(line);
+
+                } else if (bk < k2) { // |  <--|---
+                    t = calc_progress<I>(a, b, k2);
+                    slice.emplace_back(intersect<I>(a, b, k2, t));
+                    if (lineMetrics) slice.segStart = lineLen + segLen * t;
+                    if (isLastSeg) slice.emplace_back(b); // last point
+
+                } else if (bk == k2 && !isLastSeg) { // |  ..|<---
+                    if (lineMetrics) slice.segStart = lineLen + segLen;
+                    slice.emplace_back(b);
+                }
+            } else {
+                slice.emplace_back(a);
+
+                if (bk < k1) { // <--|---  |
+                    t = calc_progress<I>(a, b, k1);
+                    slice.emplace_back(intersect<I>(a, b, k1, t));
+                    if (lineMetrics) slice.segEnd = lineLen + segLen * t;
+                    slices.emplace_back(std::move(slice));
+                    slice = newSlice(line);
+
+                } else if (bk > k2) { // |  ---|-->
+                    t = calc_progress<I>(a, b, k2);
+                    slice.emplace_back(intersect<I>(a, b, k2, t));
+                    if (lineMetrics) slice.segEnd = lineLen + segLen * t;
+                    slices.emplace_back(std::move(slice));
+                    slice = newSlice(line);
+
+                } else if (isLastSeg) { // | --> |
+                    slice.emplace_back(b);
+                }
+            }
+
+            if (lineMetrics) lineLen += segLen;
+        }
+
+        if (!slice.empty()) { // add the final slice
+            if (lineMetrics) slice.segEnd = lineLen;
+            slices.emplace_back(std::move(slice));
+        }
+    }
+
+    vt_linear_ring clipRing(const vt_linear_ring& ring) const {
+        const size_t len = ring.size();
+        vt_linear_ring slice;
+        slice.area = ring.area;
+
+        if (len < 2)
+            return slice;
+
+        for (size_t i = 0; i < (len - 1); ++i) {
+            const auto& a = ring[i];
+            const auto& b = ring[i + 1];
+            const double ak = get<I>(a);
+            const double bk = get<I>(b);
+
+            if (ak < k1) {
+                if (bk > k1) {
+                    // ---|-->  |
+                    slice.emplace_back(intersect<I>(a, b, k1, calc_progress<I>(a, b, k1)));
+                    if (bk > k2)
+                        // ---|-----|-->
+                        slice.emplace_back(intersect<I>(a, b, k2, calc_progress<I>(a, b, k2)));
+                    else if (i == len - 2)
+                        slice.emplace_back(b); // last point
+                }
+            } else if (ak > k2) {
+                if (bk < k2) { // |  <--|---
+                    slice.emplace_back(intersect<I>(a, b, k2, calc_progress<I>(a, b, k2)));
+                    if (bk < k1) // <--|-----|---
+                        slice.emplace_back(intersect<I>(a, b, k1, calc_progress<I>(a, b, k1)));
+                    else if (i == len - 2)
+                        slice.emplace_back(b); // last point
+                }
+            } else {
+                // | --> |
+                slice.emplace_back(a);
+                if (bk < k1)
+                    // <--|---  |
+                    slice.emplace_back(intersect<I>(a, b, k1, calc_progress<I>(a, b, k1)));
+                else if (bk > k2)
+                    // |  ---|-->
+                    slice.emplace_back(intersect<I>(a, b, k2, calc_progress<I>(a, b, k2)));
+            }
+        }
+
+        // close the polygon if its endpoints are not the same after clipping
+        if (!slice.empty()) {
+            const auto& first = slice.front();
+            const auto& last = slice.back();
+            if (first != last) {
+                slice.emplace_back(first);
+            }
+        }
+
+        return slice;
+    }
+};
+
+/* clip features between two axis-parallel lines:
+ *     |        |
+ *  ___|___     |     /
+ * /   |   \____|____/
+ *     |        |
+ */
+
+template <uint8_t I>
+inline vt_features clip(const vt_features& features,
+                        const double k1,
+                        const double k2,
+                        const double minAll,
+                        const double maxAll,
+                        const bool lineMetrics) {
+
+    if (minAll >= k1 && maxAll < k2) // trivial accept
+        return features;
+
+    if (maxAll < k1 || minAll >= k2) // trivial reject
+        return {};
+
+    vt_features clipped;
+    clipped.reserve(features.size());
+
+    for (const auto& feature : features) {
+        const auto& geom = feature.geometry;
+        assert(feature.properties);
+        const auto& props = feature.properties;
+        const auto& id = feature.id;
+
+        const double min = get<I>(feature.bbox.min);
+        const double max = get<I>(feature.bbox.max);
+
+        if (min >= k1 && max < k2) { // trivial accept
+            clipped.emplace_back(feature);
+
+        } else if (max < k1 || min >= k2) { // trivial reject
+            continue;
+
+        } else {
+            const auto& clippedGeom = vt_geometry::visit(geom, clipper<I>{ k1, k2, lineMetrics });
+
+            clippedGeom.match(
+                [&](const auto&) {
+                    clipped.emplace_back(clippedGeom, props, id);
+                },
+                [&](const vt_multi_line_string& result) {
+                    if (lineMetrics) {
+                        for (const auto& segment : result) {
+                            clipped.emplace_back(segment, props, id);
+                        }
+                    } else {
+                        clipped.emplace_back(clippedGeom, props, id);
+                    }
+                }
+            );
+        }
+    }
+
+    return clipped;
+}
+
+} // namespace detail
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/convert.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/convert.hpp
new file mode 100644
index 000000000..309008213
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/convert.hpp
@@ -0,0 +1,120 @@
+#pragma once
+
+#include <mapbox/geojsonvt/simplify.hpp>
+#include <mapbox/geojsonvt/types.hpp>
+#include <mapbox/geometry.hpp>
+#include <mapbox/feature.hpp>
+
+#include <algorithm>
+#include <cmath>
+
+namespace mapbox {
+namespace geojsonvt {
+namespace detail {
+
+struct project {
+    const double tolerance;
+    using result_type = vt_geometry;
+
+    vt_empty operator()(const geometry::empty& empty) {
+        return empty;
+    }
+
+    vt_point operator()(const geometry::point<double>& p) {
+        const double sine = std::sin(p.y * M_PI / 180);
+        const double x = p.x / 360 + 0.5;
+        const double y =
+            std::max(std::min(0.5 - 0.25 * std::log((1 + sine) / (1 - sine)) / M_PI, 1.0), 0.0);
+        return { x, y, 0.0 };
+    }
+
+    vt_line_string operator()(const geometry::line_string<double>& points) {
+        vt_line_string result;
+        const size_t len = points.size();
+
+        if (len == 0)
+            return result;
+
+        result.reserve(len);
+
+        for (const auto& p : points) {
+            result.push_back(operator()(p));
+        }
+
+        for (size_t i = 0; i < len - 1; ++i) {
+            const auto& a = result[i];
+            const auto& b = result[i + 1];
+            result.dist += ::hypot((b.x - a.x), (b.y - a.y));
+        }
+
+        simplify(result, tolerance);
+
+        result.segStart = 0;
+        result.segEnd = result.dist;
+
+        return result;
+    }
+
+    vt_linear_ring operator()(const geometry::linear_ring<double>& ring) {
+        vt_linear_ring result;
+        const size_t len = ring.size();
+
+        if (len == 0)
+            return result;
+
+        result.reserve(len);
+
+        for (const auto& p : ring) {
+            result.push_back(operator()(p));
+        }
+
+        double area = 0.0;
+
+        for (size_t i = 0; i < len - 1; ++i) {
+            const auto& a = result[i];
+            const auto& b = result[i + 1];
+            area += a.x * b.y - b.x * a.y;
+        }
+        result.area = std::abs(area / 2);
+
+        simplify(result, tolerance);
+
+        return result;
+    }
+
+    vt_geometry operator()(const geometry::geometry<double>& geometry) {
+        return geometry::geometry<double>::visit(geometry, project{ tolerance });
+    }
+
+    // Handles polygon, multi_*, geometry_collection.
+    template <class T>
+    auto operator()(const T& vector) {
+        typename vt_geometry_type<T>::type result;
+        result.reserve(vector.size());
+        for (const auto& e : vector) {
+            result.push_back(operator()(e));
+        }
+        return result;
+    }
+};
+
+inline vt_features convert(const feature::feature_collection<double>& features,
+                           const double tolerance, bool generateId) {
+    vt_features projected;
+    projected.reserve(features.size());
+    uint64_t genId = 0;
+    for (const auto& feature : features) {
+        identifier featureId = feature.id;
+        if (generateId) {
+            featureId = { uint64_t {genId++} };
+        }
+        projected.emplace_back(
+            geometry::geometry<double>::visit(feature.geometry, project{ tolerance }),
+            feature.properties, featureId);
+    }
+    return projected;
+}
+
+} // namespace detail
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/simplify.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/simplify.hpp
new file mode 100644
index 000000000..8bc20e58d
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/simplify.hpp
@@ -0,0 +1,84 @@
+#pragma once
+
+#include <mapbox/geojsonvt/types.hpp>
+
+namespace mapbox {
+namespace geojsonvt {
+namespace detail {
+
+// square distance from a point to a segment
+inline double getSqSegDist(const vt_point& p, const vt_point& a, const vt_point& b) {
+    double x = a.x;
+    double y = a.y;
+    double dx = b.x - a.x;
+    double dy = b.y - a.y;
+
+    if ((dx != 0.0) || (dy != 0.0)) {
+
+        const double t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy);
+
+        if (t > 1) {
+            x = b.x;
+            y = b.y;
+
+        } else if (t > 0) {
+            x += dx * t;
+            y += dy * t;
+        }
+    }
+
+    dx = p.x - x;
+    dy = p.y - y;
+
+    return dx * dx + dy * dy;
+}
+
+// calculate simplification data using optimized Douglas-Peucker algorithm
+inline void simplify(std::vector<vt_point>& points, size_t first, size_t last, double sqTolerance) {
+    double maxSqDist = sqTolerance;
+    size_t index = 0;
+    const int64_t mid = first + ((last - first) >> 1);
+    int64_t minPosToMid = last - first;
+
+    for (auto i = first + 1; i < last; i++) {
+        const double sqDist = getSqSegDist(points[i], points[first], points[last]);
+
+        if (sqDist > maxSqDist) {
+            index = i;
+            maxSqDist = sqDist;
+
+        } else if (sqDist == maxSqDist) {
+            // a workaround to ensure we choose a pivot close to the middle of the list,
+            // reducing recursion depth, for certain degenerate inputs
+            // https://github.com/mapbox/geojson-vt/issues/104
+            auto posToMid = std::abs(static_cast<int64_t>(i) - mid);
+            if (posToMid < minPosToMid) {
+                index = i;
+                minPosToMid = posToMid;
+            }
+        }
+    }
+
+    if (maxSqDist > sqTolerance) {
+        // save the point importance in squared pixels as a z coordinate
+        points[index].z = maxSqDist;
+        if (index - first > 1)
+            simplify(points, first, index, sqTolerance);
+        if (last - index > 1)
+            simplify(points, index, last, sqTolerance);
+    }
+}
+
+inline void simplify(std::vector<vt_point>& points, double tolerance) {
+    const size_t len = points.size();
+
+    // always retain the endpoints (1 is the max value)
+    points[0].z = 1.0;
+    points[len - 1].z = 1.0;
+
+    simplify(points, 0, len - 1, tolerance * tolerance);
+}
+
+} // namespace detail
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/tile.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/tile.hpp
new file mode 100644
index 000000000..1586b7168
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/tile.hpp
@@ -0,0 +1,209 @@
+#pragma once
+
+#include <algorithm>
+#include <cmath>
+#include <mapbox/geojsonvt/types.hpp>
+
+namespace mapbox {
+namespace geojsonvt {
+
+struct Tile {
+    mapbox::feature::feature_collection<int16_t> features;
+    uint32_t num_points = 0;
+    uint32_t num_simplified = 0;
+};
+
+namespace detail {
+
+class InternalTile {
+public:
+    const uint16_t extent;
+    const uint8_t z;
+    const uint32_t x;
+    const uint32_t y;
+
+    const double z2;
+    const double tolerance;
+    const double sq_tolerance;
+    const bool lineMetrics;
+
+    vt_features source_features;
+    mapbox::geometry::box<double> bbox = { { 2, 1 }, { -1, 0 } };
+
+    Tile tile;
+
+    InternalTile(const vt_features& source,
+                 const uint8_t z_,
+                 const uint32_t x_,
+                 const uint32_t y_,
+                 const uint16_t extent_,
+                 const double tolerance_,
+                 const bool lineMetrics_)
+        : extent(extent_),
+          z(z_),
+          x(x_),
+          y(y_),
+          z2(std::pow(2, z)),
+          tolerance(tolerance_),
+          sq_tolerance(tolerance_ * tolerance_),
+          lineMetrics(lineMetrics_) {
+
+        tile.features.reserve(source.size());
+        for (const auto& feature : source) {
+            const auto& geom = feature.geometry;
+            assert(feature.properties);
+            const auto& props = feature.properties;
+            const auto& id = feature.id;
+
+            tile.num_points += feature.num_points;
+
+            vt_geometry::visit(geom, [&](const auto& g) {
+                // `this->` is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636
+                this->addFeature(g, *props, id);
+            });
+
+            bbox.min.x = std::min(feature.bbox.min.x, bbox.min.x);
+            bbox.min.y = std::min(feature.bbox.min.y, bbox.min.y);
+            bbox.max.x = std::max(feature.bbox.max.x, bbox.max.x);
+            bbox.max.y = std::max(feature.bbox.max.y, bbox.max.y);
+        }
+    }
+
+private:
+    void addFeature(const vt_empty& empty, const property_map& props, const identifier& id) {
+        tile.features.emplace_back(transform(empty), props, id);
+    }
+
+    void
+    addFeature(const vt_point& point, const property_map& props, const identifier& id) {
+        tile.features.emplace_back(transform(point), props, id);
+    }
+
+    void addFeature(const vt_line_string& line,
+                    const property_map& props,
+                    const identifier& id) {
+        const auto new_line = transform(line);
+        if (!new_line.empty()) {
+            if (lineMetrics) {
+                property_map newProps = props;
+                newProps.emplace(std::make_pair<std::string, value>("mapbox_clip_start", line.segStart / line.dist));
+                newProps.emplace(std::make_pair<std::string, value>("mapbox_clip_end", line.segEnd / line.dist));
+                tile.features.emplace_back(std::move(new_line), std::move(newProps), id);
+            } else
+                tile.features.emplace_back(std::move(new_line), props, id);
+        }
+    }
+
+    void addFeature(const vt_polygon& polygon,
+                    const property_map& props,
+                    const identifier& id) {
+        const auto new_polygon = transform(polygon);
+        if (!new_polygon.empty())
+            tile.features.emplace_back(std::move(new_polygon), props, id);
+    }
+
+    void addFeature(const vt_geometry_collection& collection,
+                    const property_map& props,
+                    const identifier& id) {
+        for (const auto& geom : collection) {
+            vt_geometry::visit(geom, [&](const auto& g) {
+                // `this->` is a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61636
+                this->addFeature(g, props, id);
+            });
+        }
+    }
+
+    template <class T>
+    void addFeature(const T& multi, const property_map& props, const identifier& id) {
+        const auto new_multi = transform(multi);
+
+        switch (new_multi.size()) {
+        case 0:
+            break;
+        case 1:
+            tile.features.emplace_back(std::move(new_multi[0]), props, id);
+            break;
+        default:
+            tile.features.emplace_back(std::move(new_multi), props, id);
+            break;
+        }
+    }
+
+    mapbox::geometry::empty transform(const vt_empty& empty) {
+        return empty;
+    }
+
+    mapbox::geometry::point<int16_t> transform(const vt_point& p) {
+        ++tile.num_simplified;
+        return { static_cast<int16_t>(::round((p.x * z2 - x) * extent)),
+                 static_cast<int16_t>(::round((p.y * z2 - y) * extent)) };
+    }
+
+    mapbox::geometry::multi_point<int16_t> transform(const vt_multi_point& points) {
+        mapbox::geometry::multi_point<int16_t> result;
+        result.reserve(points.size());
+        for (const auto& p : points) {
+            result.emplace_back(transform(p));
+        }
+        return result;
+    }
+
+    mapbox::geometry::line_string<int16_t> transform(const vt_line_string& line) {
+        mapbox::geometry::line_string<int16_t> result;
+        if (line.dist > tolerance) {
+            result.reserve(line.size());
+            for (const auto& p : line) {
+                if (p.z > sq_tolerance)
+                    result.emplace_back(transform(p));
+            }
+        }
+        return result;
+    }
+
+    mapbox::geometry::linear_ring<int16_t> transform(const vt_linear_ring& ring) {
+        mapbox::geometry::linear_ring<int16_t> result;
+        if (ring.area > sq_tolerance) {
+            result.reserve(ring.size());
+            for (const auto& p : ring) {
+                if (p.z > sq_tolerance)
+                    result.emplace_back(transform(p));
+            }
+        }
+        return result;
+    }
+
+    mapbox::geometry::multi_line_string<int16_t> transform(const vt_multi_line_string& lines) {
+        mapbox::geometry::multi_line_string<int16_t> result;
+        result.reserve(lines.size());
+        for (const auto& line : lines) {
+            if (line.dist > tolerance)
+                result.emplace_back(transform(line));
+        }
+        return result;
+    }
+
+    mapbox::geometry::polygon<int16_t> transform(const vt_polygon& rings) {
+        mapbox::geometry::polygon<int16_t> result;
+        result.reserve(rings.size());
+        for (const auto& ring : rings) {
+            if (ring.area > sq_tolerance)
+                result.emplace_back(transform(ring));
+        }
+        return result;
+    }
+
+    mapbox::geometry::multi_polygon<int16_t> transform(const vt_multi_polygon& polygons) {
+        mapbox::geometry::multi_polygon<int16_t> result;
+        result.reserve(polygons.size());
+        for (const auto& polygon : polygons) {
+            const auto p = transform(polygon);
+            if (!p.empty())
+                result.emplace_back(std::move(p));
+        }
+        return result;
+    }
+};
+
+} // namespace detail
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/types.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/types.hpp
new file mode 100644
index 000000000..1ba9ebabf
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/types.hpp
@@ -0,0 +1,195 @@
+#pragma once
+
+#include <mapbox/geometry.hpp>
+#include <mapbox/feature.hpp>
+#include <mapbox/variant.hpp>
+
+#include <algorithm>
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include <memory>
+
+namespace mapbox {
+namespace geojsonvt {
+namespace detail {
+
+using vt_empty = mapbox::geometry::empty;
+
+struct vt_point : mapbox::geometry::point<double> {
+    double z = 0.0; // simplification tolerance
+
+    vt_point(double x_, double y_, double z_) : mapbox::geometry::point<double>(x_, y_), z(z_) {
+    }
+
+    vt_point(double x_, double y_) : vt_point(x_, y_, 0.0) {
+    }
+};
+
+template <uint8_t I, typename T>
+inline double get(const T&);
+
+template <>
+inline double get<0>(const vt_point& p) {
+    return p.x;
+}
+template <>
+inline double get<1>(const vt_point& p) {
+    return p.y;
+}
+template <>
+inline double get<0>(const mapbox::geometry::point<double>& p) {
+    return p.x;
+}
+template <>
+inline double get<1>(const mapbox::geometry::point<double>& p) {
+    return p.y;
+}
+
+template <uint8_t I>
+inline double calc_progress(const vt_point&, const vt_point&, const double);
+
+template <>
+inline double calc_progress<0>(const vt_point& a, const vt_point& b, const double x) {
+    return (x - a.x) / (b.x - a.x);
+}
+
+template <>
+inline double calc_progress<1>(const vt_point& a, const vt_point& b, const double y) {
+    return (y - a.y) / (b.y - a.y);
+}
+
+template <uint8_t I>
+inline vt_point intersect(const vt_point&, const vt_point&, const double, const double);
+
+template <>
+inline vt_point intersect<0>(const vt_point& a, const vt_point& b, const double x, const double t) {
+    const double y = (b.y - a.y) * t + a.y;
+    return { x, y, 1.0 };
+}
+template <>
+inline vt_point intersect<1>(const vt_point& a, const vt_point& b, const double y, const double t) {
+    const double x = (b.x - a.x) * t + a.x;
+    return { x, y, 1.0 };
+}
+
+using vt_multi_point = std::vector<vt_point>;
+
+struct vt_line_string : std::vector<vt_point> {
+    using container_type = std::vector<vt_point>;
+    vt_line_string() = default;
+    vt_line_string(std::initializer_list<vt_point> args)
+      : container_type(std::move(args)) {}
+
+    double dist = 0.0; // line length
+    double segStart = 0.0;
+    double segEnd = 0.0; // segStart and segEnd are distance along a line in tile units, when lineMetrics = true
+};
+
+struct vt_linear_ring : std::vector<vt_point> {
+    using container_type = std::vector<vt_point>;
+    vt_linear_ring() = default;
+    vt_linear_ring(std::initializer_list<vt_point> args)
+      : container_type(std::move(args)) {}
+
+    double area = 0.0; // polygon ring area
+};
+
+using vt_multi_line_string = std::vector<vt_line_string>;
+using vt_polygon = std::vector<vt_linear_ring>;
+using vt_multi_polygon = std::vector<vt_polygon>;
+
+struct vt_geometry_collection;
+
+using vt_geometry = mapbox::util::variant<vt_empty,
+                                          vt_point,
+                                          vt_line_string,
+                                          vt_polygon,
+                                          vt_multi_point,
+                                          vt_multi_line_string,
+                                          vt_multi_polygon,
+                                          vt_geometry_collection>;
+
+struct vt_geometry_collection : std::vector<vt_geometry> {};
+
+using null_value = mapbox::feature::null_value_t;
+using property_map = mapbox::feature::property_map;
+using identifier = mapbox::feature::identifier;
+using value = mapbox::feature::value;
+
+template <class T>
+struct vt_geometry_type;
+
+template <>
+struct vt_geometry_type<geometry::empty> {
+    using type = vt_empty;
+};
+template <>
+struct vt_geometry_type<geometry::point<double>> {
+    using type = vt_point;
+};
+template <>
+struct vt_geometry_type<geometry::line_string<double>> {
+    using type = vt_line_string;
+};
+template <>
+struct vt_geometry_type<geometry::polygon<double>> {
+    using type = vt_polygon;
+};
+template <>
+struct vt_geometry_type<geometry::multi_point<double>> {
+    using type = vt_multi_point;
+};
+template <>
+struct vt_geometry_type<geometry::multi_line_string<double>> {
+    using type = vt_multi_line_string;
+};
+template <>
+struct vt_geometry_type<geometry::multi_polygon<double>> {
+    using type = vt_multi_polygon;
+};
+template <>
+struct vt_geometry_type<geometry::geometry<double>> {
+    using type = vt_geometry;
+};
+template <>
+struct vt_geometry_type<geometry::geometry_collection<double>> {
+    using type = vt_geometry_collection;
+};
+
+struct vt_feature {
+    vt_geometry geometry;
+    std::shared_ptr<const property_map> properties;
+    identifier id;
+
+    mapbox::geometry::box<double> bbox = { { 2, 1 }, { -1, 0 } };
+    uint32_t num_points = 0;
+
+    vt_feature(const vt_geometry& geom, std::shared_ptr<const property_map> props, const identifier& id_)
+        : geometry(geom), properties(std::move(props)), id(id_) {
+        assert(properties);
+        processGeometry();
+    }
+
+    vt_feature(const vt_geometry& geom, const property_map& props, const identifier& id_)
+        : geometry(geom), properties(std::make_shared<property_map>(props)), id(id_) {
+        processGeometry();
+    }
+
+private:
+    void processGeometry() {
+        mapbox::geometry::for_each_point(geometry, [&](const vt_point& p) {
+            bbox.min.x = std::min(p.x, bbox.min.x);
+            bbox.min.y = std::min(p.y, bbox.min.y);
+            bbox.max.x = std::max(p.x, bbox.max.x);
+            bbox.max.y = std::max(p.y, bbox.max.y);
+            ++num_points;
+        });
+    }
+};
+
+using vt_features = std::vector<vt_feature>;
+
+} // namespace detail
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/wrap.hpp b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/wrap.hpp
new file mode 100644
index 000000000..a4f1bb85c
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/geojsonvt/6.6.5/include/mapbox/geojsonvt/wrap.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <mapbox/geojsonvt/clip.hpp>
+#include <mapbox/geojsonvt/types.hpp>
+
+namespace mapbox {
+namespace geojsonvt {
+namespace detail {
+
+inline void shiftCoords(vt_features& features, double offset) {
+    for (auto& feature : features) {
+        mapbox::geometry::for_each_point(feature.geometry,
+                                         [offset](vt_point& point) { point.x += offset; });
+        feature.bbox.min.x += offset;
+        feature.bbox.max.x += offset;
+    }
+}
+
+inline vt_features wrap(const vt_features& features, double buffer, const bool lineMetrics) {
+    // left world copy
+    auto left = clip<0>(features, -1 - buffer, buffer, -1, 2, lineMetrics);
+    // right world copy
+    auto right = clip<0>(features, 1 - buffer, 2 + buffer, -1, 2, lineMetrics);
+
+    if (left.empty() && right.empty())
+        return features;
+
+    // center world copy
+    auto merged = clip<0>(features, -buffer, 1 + buffer, -1, 2, lineMetrics);
+
+    if (!left.empty()) {
+        // merge left into center
+        shiftCoords(left, 1.0);
+        merged.insert(merged.begin(), left.begin(), left.end());
+    }
+    if (!right.empty()) {
+        // merge right into center
+        shiftCoords(right, -1.0);
+        merged.insert(merged.end(), right.begin(), right.end());
+    }
+    return merged;
+}
+
+} // namespace detail
+} // namespace geojsonvt
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.1-1/LICENSE b/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.1-1/LICENSE
deleted file mode 100644
index 3c8f67eab..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.1-1/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright (c) 2016, Vladimir Agafonkin
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.1-1/include/kdbush.hpp b/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.1-1/include/kdbush.hpp
deleted file mode 100644
index b5938c1a7..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.1-1/include/kdbush.hpp
+++ /dev/null
@@ -1,210 +0,0 @@
-#pragma once
-
-#include <algorithm>
-#include <cmath>
-#include <cstdint>
-#include <tuple>
-#include <vector>
-#include <cassert>
-
-namespace kdbush {
-
-template <std::uint8_t I, typename T>
-struct nth {
-    inline static typename std::tuple_element<I, T>::type get(const T &t) {
-        return std::get<I>(t);
-    }
-};
-
-template <typename TPoint, typename TIndex = std::size_t>
-class KDBush {
-
-public:
-    using TNumber = decltype(nth<0, TPoint>::get(std::declval<TPoint>()));
-    static_assert(
-        std::is_same<TNumber, decltype(nth<1, TPoint>::get(std::declval<TPoint>()))>::value,
-        "point component types must be identical");
-
-    static const std::uint8_t defaultNodeSize = 64;
-
-    KDBush(const std::uint8_t nodeSize_ = defaultNodeSize) : nodeSize(nodeSize_) {
-    }
-
-    KDBush(const std::vector<TPoint> &points_, const std::uint8_t nodeSize_ = defaultNodeSize)
-        : KDBush(std::begin(points_), std::end(points_), nodeSize_) {
-    }
-
-    template <typename TPointIter>
-    KDBush(const TPointIter &points_begin,
-           const TPointIter &points_end,
-           const std::uint8_t nodeSize_ = defaultNodeSize)
-        : nodeSize(nodeSize_) {
-        fill(points_begin, points_end);
-    }
-
-    void fill(const std::vector<TPoint> &points_) {
-        fill(std::begin(points_), std::end(points_));
-    }
-
-    template <typename TPointIter>
-    void fill(const TPointIter &points_begin, const TPointIter &points_end) {
-        assert(points.empty());
-        const TIndex size = static_cast<TIndex>(std::distance(points_begin, points_end));
-
-        points.reserve(size);
-        ids.reserve(size);
-
-        TIndex i = 0;
-        for (auto p = points_begin; p != points_end; p++) {
-            points.emplace_back(nth<0, TPoint>::get(*p), nth<1, TPoint>::get(*p));
-            ids.push_back(i++);
-        }
-
-        sortKD(0, size - 1, 0);
-    }
-
-    template <typename TVisitor>
-    void range(const TNumber minX,
-               const TNumber minY,
-               const TNumber maxX,
-               const TNumber maxY,
-               const TVisitor &visitor) {
-        range(minX, minY, maxX, maxY, visitor, 0, static_cast<TIndex>(ids.size() - 1), 0);
-    }
-
-    template <typename TVisitor>
-    void within(const TNumber qx, const TNumber qy, const TNumber r, const TVisitor &visitor) {
-        within(qx, qy, r, visitor, 0, static_cast<TIndex>(ids.size() - 1), 0);
-    }
-
-private:
-    std::vector<TIndex> ids;
-    std::vector<std::pair<TNumber, TNumber>> points;
-    std::uint8_t nodeSize;
-
-    template <typename TVisitor>
-    void range(const TNumber minX,
-               const TNumber minY,
-               const TNumber maxX,
-               const TNumber maxY,
-               const TVisitor &visitor,
-               const TIndex left,
-               const TIndex right,
-               const std::uint8_t axis) {
-
-        if (right - left <= nodeSize) {
-            for (auto i = left; i <= right; i++) {
-                const TNumber x = std::get<0>(points[i]);
-                const TNumber y = std::get<1>(points[i]);
-                if (x >= minX && x <= maxX && y >= minY && y <= maxY) visitor(ids[i]);
-            }
-            return;
-        }
-
-        const TIndex m = (left + right) >> 1;
-        const TNumber x = std::get<0>(points[m]);
-        const TNumber y = std::get<1>(points[m]);
-
-        if (x >= minX && x <= maxX && y >= minY && y <= maxY) visitor(ids[m]);
-
-        if (axis == 0 ? minX <= x : minY <= y)
-            range(minX, minY, maxX, maxY, visitor, left, m - 1, (axis + 1) % 2);
-
-        if (axis == 0 ? maxX >= x : maxY >= y)
-            range(minX, minY, maxX, maxY, visitor, m + 1, right, (axis + 1) % 2);
-    }
-
-    template <typename TVisitor>
-    void within(const TNumber qx,
-                const TNumber qy,
-                const TNumber r,
-                const TVisitor &visitor,
-                const TIndex left,
-                const TIndex right,
-                const std::uint8_t axis) {
-
-        const TNumber r2 = r * r;
-
-        if (right - left <= nodeSize) {
-            for (auto i = left; i <= right; i++) {
-                const TNumber x = std::get<0>(points[i]);
-                const TNumber y = std::get<1>(points[i]);
-                if (sqDist(x, y, qx, qy) <= r2) visitor(ids[i]);
-            }
-            return;
-        }
-
-        const TIndex m = (left + right) >> 1;
-        const TNumber x = std::get<0>(points[m]);
-        const TNumber y = std::get<1>(points[m]);
-
-        if (sqDist(x, y, qx, qy) <= r2) visitor(ids[m]);
-
-        if (axis == 0 ? qx - r <= x : qy - r <= y)
-            within(qx, qy, r, visitor, left, m - 1, (axis + 1) % 2);
-
-        if (axis == 0 ? qx + r >= x : qy + r >= y)
-            within(qx, qy, r, visitor, m + 1, right, (axis + 1) % 2);
-    }
-
-    void sortKD(const TIndex left, const TIndex right, const std::uint8_t axis) {
-        if (right - left <= nodeSize) return;
-        const TIndex m = (left + right) >> 1;
-        if (axis == 0) {
-            select<0>(m, left, right);
-        } else {
-            select<1>(m, left, right);
-        }
-        sortKD(left, m - 1, (axis + 1) % 2);
-        sortKD(m + 1, right, (axis + 1) % 2);
-    }
-
-    template <std::uint8_t I>
-    void select(const TIndex k, TIndex left, TIndex right) {
-
-        while (right > left) {
-            if (right - left > 600) {
-                const double n = right - left + 1;
-                const double m = k - left + 1;
-                const double z = std::log(n);
-                const double s = 0.5 * std::exp(2 * z / 3);
-                const double r =
-                    k - m * s / n + 0.5 * std::sqrt(z * s * (1 - s / n)) * (2 * m < n ? -1 : 1);
-                select<I>(k, std::max(left, TIndex(r)), std::min(right, TIndex(r + s)));
-            }
-
-            const TNumber t = std::get<I>(points[k]);
-            TIndex i = left;
-            TIndex j = right;
-
-            swapItem(left, k);
-            if (std::get<I>(points[right]) > t) swapItem(left, right);
-
-            while (i < j) {
-                swapItem(i++, j--);
-                while (std::get<I>(points[i]) < t) i++;
-                while (std::get<I>(points[j]) > t) j--;
-            }
-
-            if (std::get<I>(points[left]) == t)
-                swapItem(left, j);
-            else {
-                swapItem(++j, right);
-            }
-
-            if (j <= k) left = j + 1;
-            if (k <= j) right = j - 1;
-        }
-    }
-
-    void swapItem(const TIndex i, const TIndex j) {
-        std::iter_swap(ids.begin() + i, ids.begin() + j);
-        std::iter_swap(points.begin() + i, points.begin() + j);
-    }
-
-    TNumber sqDist(const TNumber ax, const TNumber ay, const TNumber bx, const TNumber by) {
-        return std::pow(ax - bx, 2) + std::pow(ay - by, 2);
-    }
-};
-
-} // namespace kdbush
diff --git a/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.3/LICENSE b/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.3/LICENSE
new file mode 100644
index 000000000..3c8f67eab
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.3/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2016, Vladimir Agafonkin
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.3/include/kdbush.hpp b/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.3/include/kdbush.hpp
new file mode 100644
index 000000000..26a343232
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/kdbush/0.1.3/include/kdbush.hpp
@@ -0,0 +1,220 @@
+#pragma once
+
+#include <algorithm>
+#include <cmath>
+#include <cstdint>
+#include <tuple>
+#include <vector>
+#include <cassert>
+
+namespace kdbush {
+
+template <std::uint8_t I, typename T>
+struct nth {
+    inline static typename std::tuple_element<I, T>::type get(const T &t) {
+        return std::get<I>(t);
+    }
+};
+
+template <typename TPoint, typename TIndex = std::size_t>
+class KDBush {
+
+public:
+    using TNumber = decltype(nth<0, TPoint>::get(std::declval<TPoint>()));
+    static_assert(
+        std::is_same<TNumber, decltype(nth<1, TPoint>::get(std::declval<TPoint>()))>::value,
+        "point component types must be identical");
+
+    static const std::uint8_t defaultNodeSize = 64;
+
+    KDBush(const std::uint8_t nodeSize_ = defaultNodeSize) : nodeSize(nodeSize_) {
+    }
+
+    KDBush(const std::vector<TPoint> &points_, const std::uint8_t nodeSize_ = defaultNodeSize)
+        : KDBush(std::begin(points_), std::end(points_), nodeSize_) {
+    }
+
+    template <typename TPointIter>
+    KDBush(const TPointIter &points_begin,
+           const TPointIter &points_end,
+           const std::uint8_t nodeSize_ = defaultNodeSize)
+        : nodeSize(nodeSize_) {
+        fill(points_begin, points_end);
+    }
+
+    void fill(const std::vector<TPoint> &points_) {
+        fill(std::begin(points_), std::end(points_));
+    }
+
+    template <typename TPointIter>
+    void fill(const TPointIter &points_begin, const TPointIter &points_end) {
+        assert(points.empty());
+        const TIndex size = static_cast<TIndex>(std::distance(points_begin, points_end));
+
+        if (size == 0) return;
+
+        points.reserve(size);
+        ids.reserve(size);
+
+        TIndex i = 0;
+        for (auto p = points_begin; p != points_end; p++) {
+            points.emplace_back(nth<0, TPoint>::get(*p), nth<1, TPoint>::get(*p));
+            ids.push_back(i++);
+        }
+
+        sortKD(0, size - 1, 0);
+    }
+
+    template <typename TVisitor>
+    void range(const TNumber minX,
+               const TNumber minY,
+               const TNumber maxX,
+               const TNumber maxY,
+               const TVisitor &visitor) const {
+        range(minX, minY, maxX, maxY, visitor, 0, static_cast<TIndex>(ids.size() - 1), 0);
+    }
+
+    template <typename TVisitor>
+    void within(const TNumber qx, const TNumber qy, const TNumber r, const TVisitor &visitor) const {
+        within(qx, qy, r, visitor, 0, static_cast<TIndex>(ids.size() - 1), 0);
+    }
+
+protected:
+    std::vector<TIndex> ids;
+    std::vector<std::pair<TNumber, TNumber>> points;
+
+private:
+    const std::uint8_t nodeSize;
+
+    template <typename TVisitor>
+    void range(const TNumber minX,
+               const TNumber minY,
+               const TNumber maxX,
+               const TNumber maxY,
+               const TVisitor &visitor,
+               const TIndex left,
+               const TIndex right,
+               const std::uint8_t axis) const {
+
+        if (points.empty()) return;
+
+        if (right - left <= nodeSize) {
+            for (auto i = left; i <= right; i++) {
+                const TNumber x = std::get<0>(points[i]);
+                const TNumber y = std::get<1>(points[i]);
+                if (x >= minX && x <= maxX && y >= minY && y <= maxY) visitor(ids[i]);
+            }
+            return;
+        }
+
+        const TIndex m = (left + right) >> 1;
+        const TNumber x = std::get<0>(points[m]);
+        const TNumber y = std::get<1>(points[m]);
+
+        if (x >= minX && x <= maxX && y >= minY && y <= maxY) visitor(ids[m]);
+
+        if (axis == 0 ? minX <= x : minY <= y)
+            range(minX, minY, maxX, maxY, visitor, left, m - 1, (axis + 1) % 2);
+
+        if (axis == 0 ? maxX >= x : maxY >= y)
+            range(minX, minY, maxX, maxY, visitor, m + 1, right, (axis + 1) % 2);
+    }
+
+    template <typename TVisitor>
+    void within(const TNumber qx,
+                const TNumber qy,
+                const TNumber r,
+                const TVisitor &visitor,
+                const TIndex left,
+                const TIndex right,
+                const std::uint8_t axis) const {
+
+        if (points.empty()) return;
+
+        const TNumber r2 = r * r;
+
+        if (right - left <= nodeSize) {
+            for (auto i = left; i <= right; i++) {
+                const TNumber x = std::get<0>(points[i]);
+                const TNumber y = std::get<1>(points[i]);
+                if (sqDist(x, y, qx, qy) <= r2) visitor(ids[i]);
+            }
+            return;
+        }
+
+        const TIndex m = (left + right) >> 1;
+        const TNumber x = std::get<0>(points[m]);
+        const TNumber y = std::get<1>(points[m]);
+
+        if (sqDist(x, y, qx, qy) <= r2) visitor(ids[m]);
+
+        if (axis == 0 ? qx - r <= x : qy - r <= y)
+            within(qx, qy, r, visitor, left, m - 1, (axis + 1) % 2);
+
+        if (axis == 0 ? qx + r >= x : qy + r >= y)
+            within(qx, qy, r, visitor, m + 1, right, (axis + 1) % 2);
+    }
+
+    void sortKD(const TIndex left, const TIndex right, const std::uint8_t axis) {
+        if (right - left <= nodeSize) return;
+        const TIndex m = (left + right) >> 1;
+        if (axis == 0) {
+            select<0>(m, left, right);
+        } else {
+            select<1>(m, left, right);
+        }
+        sortKD(left, m - 1, (axis + 1) % 2);
+        sortKD(m + 1, right, (axis + 1) % 2);
+    }
+
+    template <std::uint8_t I>
+    void select(const TIndex k, TIndex left, TIndex right) {
+
+        while (right > left) {
+            if (right - left > 600) {
+                const double n = static_cast<double>(right - left + 1);
+                const double m = static_cast<double>(k - left + 1);
+                const double z = std::log(n);
+                const double s = 0.5 * std::exp(2 * z / 3);
+                const double r =
+                    k - m * s / n + 0.5 * std::sqrt(z * s * (1 - s / n)) * (2 * m < n ? -1 : 1);
+                select<I>(k, std::max(left, TIndex(r)), std::min(right, TIndex(r + s)));
+            }
+
+            const TNumber t = std::get<I>(points[k]);
+            TIndex i = left;
+            TIndex j = right;
+
+            swapItem(left, k);
+            if (std::get<I>(points[right]) > t) swapItem(left, right);
+
+            while (i < j) {
+                swapItem(i++, j--);
+                while (std::get<I>(points[i]) < t) i++;
+                while (std::get<I>(points[j]) > t) j--;
+            }
+
+            if (std::get<I>(points[left]) == t)
+                swapItem(left, j);
+            else {
+                swapItem(++j, right);
+            }
+
+            if (j <= k) left = j + 1;
+            if (k <= j) right = j - 1;
+        }
+    }
+
+    void swapItem(const TIndex i, const TIndex j) {
+        std::iter_swap(ids.begin() + static_cast<std::int32_t>(i), ids.begin() + static_cast<std::int32_t>(j));
+        std::iter_swap(points.begin() + static_cast<std::int32_t>(i), points.begin() + static_cast<std::int32_t>(j));
+    }
+
+    TNumber sqDist(const TNumber ax, const TNumber ay, const TNumber bx, const TNumber by) const {
+        auto dx = ax - bx;
+        auto dy = ay - by;
+        return dx * dx + dy * dy;
+    }
+};
+
+} // namespace kdbush
diff --git a/src/3rdparty/mapbox-gl-native/deps/supercluster/0.2.2/LICENSE b/src/3rdparty/mapbox-gl-native/deps/supercluster/0.2.2/LICENSE
deleted file mode 100644
index 14101c25a..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/supercluster/0.2.2/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright (c) 2016, Mapbox
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/3rdparty/mapbox-gl-native/deps/supercluster/0.2.2/include/supercluster.hpp b/src/3rdparty/mapbox-gl-native/deps/supercluster/0.2.2/include/supercluster.hpp
deleted file mode 100644
index 3175564c6..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/supercluster/0.2.2/include/supercluster.hpp
+++ /dev/null
@@ -1,229 +0,0 @@
-#pragma once
-
-#include <kdbush.hpp>
-#include <mapbox/geometry/feature.hpp>
-#include <mapbox/geometry/point_arithmetic.hpp>
-
-#include <algorithm>
-#include <cmath>
-#include <cstdint>
-#include <vector>
-
-#ifdef DEBUG_TIMER
-#include <chrono>
-#include <iostream>
-#endif
-
-namespace mapbox {
-namespace supercluster {
-
-using namespace mapbox::geometry;
-
-struct Cluster {
-    point<double> pos;
-    std::uint32_t num_points;
-    std::uint32_t id = 0;
-    bool visited = false;
-
-    Cluster(point<double> pos_,
-            std::uint32_t num_points_,
-            std::uint32_t id_ = 0,
-            bool visited_ = false)
-        : pos(std::move(pos_)),
-          num_points(num_points_),
-          id(id_),
-          visited(visited_) {}
-};
-
-} // namespace supercluster
-} // namespace mapbox
-
-namespace kdbush {
-
-using Cluster = mapbox::supercluster::Cluster;
-
-template <>
-struct nth<0, Cluster> {
-    inline static double get(const Cluster &c) {
-        return c.pos.x;
-    };
-};
-template <>
-struct nth<1, Cluster> {
-    inline static double get(const Cluster &c) {
-        return c.pos.y;
-    };
-};
-
-} // namespace kdbush
-
-namespace mapbox {
-namespace supercluster {
-
-#ifdef DEBUG_TIMER
-class Timer {
-public:
-    std::chrono::high_resolution_clock::time_point started;
-    Timer() {
-        started = std::chrono::high_resolution_clock::now();
-    }
-    void operator()(std::string msg) {
-        const auto now = std::chrono::high_resolution_clock::now();
-        const auto ms = std::chrono::duration_cast<std::chrono::microseconds>(now - started);
-        std::cerr << msg << ": " << double(ms.count()) / 1000 << "ms\n";
-        started = now;
-    }
-};
-#endif
-
-struct Options {
-    std::uint8_t minZoom = 0;   // min zoom to generate clusters on
-    std::uint8_t maxZoom = 16;  // max zoom level to cluster the points on
-    std::uint16_t radius = 40;  // cluster radius in pixels
-    std::uint16_t extent = 512; // tile extent (radius is calculated relative to it)
-};
-
-class Supercluster {
-    using GeoJSONPoint = point<double>;
-    using GeoJSONFeatures = feature_collection<double>;
-
-    using TilePoint = point<std::int16_t>;
-    using TileFeature = feature<std::int16_t>;
-    using TileFeatures = feature_collection<std::int16_t>;
-
-public:
-    const GeoJSONFeatures features;
-    const Options options;
-
-    Supercluster(const GeoJSONFeatures &features_, const Options options_ = Options())
-        : features(features_), options(options_) {
-
-#ifdef DEBUG_TIMER
-        Timer timer;
-#endif
-        // convert and index initial points
-        zooms.emplace(options.maxZoom + 1, features);
-#ifdef DEBUG_TIMER
-        timer(std::to_string(features.size()) + " initial points");
-#endif
-        for (int z = options.maxZoom; z >= options.minZoom; z--) {
-            // cluster points from the previous zoom level
-            const double r = options.radius / (options.extent * std::pow(2, z));
-            zooms.emplace(z, Zoom(zooms[z + 1], r));
-#ifdef DEBUG_TIMER
-            timer(std::to_string(zooms[z].clusters.size()) + " clusters");
-#endif
-        }
-    }
-
-    TileFeatures getTile(std::uint8_t z, std::uint32_t x_, std::uint32_t y) {
-        TileFeatures result;
-        auto &zoom = zooms[limitZoom(z)];
-
-        std::uint32_t z2 = std::pow(2, z);
-        double const r = static_cast<double>(options.radius) / options.extent;
-        std::int32_t x = static_cast<std::int32_t>(x_);
-
-        auto visitor = [&, this](const auto &id) {
-            auto const &c = zoom.clusters[id];
-
-            TilePoint point(::round(this->options.extent * (c.pos.x * z2 - x)),
-                            ::round(this->options.extent * (c.pos.y * z2 - y)));
-            TileFeature feature{ point };
-
-            if (c.num_points == 1) {
-                feature.properties = this->features[c.id].properties;
-            } else {
-                feature.properties["cluster"] = true;
-                feature.properties["point_count"] = static_cast<std::uint64_t>(c.num_points);
-            }
-
-            result.push_back(feature);
-        };
-
-        double const top = (y - r) / z2;
-        double const bottom = (y + 1 + r) / z2;
-
-        zoom.tree.range((x - r) / z2, top, (x + 1 + r) / z2, bottom, visitor);
-
-        if (x_ == 0) {
-            x = z2;
-            zoom.tree.range(1 - r / z2, top, 1, bottom, visitor);
-        }
-        if (x_ == z2 - 1) {
-            x = -1;
-            zoom.tree.range(0, top, r / z2, bottom, visitor);
-        }
-
-        return result;
-    }
-
-private:
-    struct Zoom {
-        kdbush::KDBush<Cluster, std::uint32_t> tree;
-        std::vector<Cluster> clusters;
-
-        Zoom() = default;
-
-        Zoom(const GeoJSONFeatures &features_) {
-            // generate a cluster object for each point
-            std::uint32_t i = 0;
-
-            for (const auto &f : features_) {
-                clusters.push_back({ project(f.geometry.get<GeoJSONPoint>()), 1, i++ });
-            }
-
-            tree.fill(clusters);
-        }
-
-        Zoom(Zoom &previous, double r) {
-            for (auto &p : previous.clusters) {
-                if (p.visited)
-                    continue;
-                p.visited = true;
-
-                auto num_points = p.num_points;
-                point<double> weight = p.pos * double(num_points);
-
-                // find all nearby points
-                previous.tree.within(p.pos.x, p.pos.y, r, [&](const auto &id) {
-                    auto &b = previous.clusters[id];
-
-                    // filter out neighbors that are already processed
-                    if (b.visited)
-                        return;
-                    b.visited = true;
-
-                    // accumulate coordinates for calculating weighted center
-                    weight += b.pos * double(b.num_points);
-                    num_points += b.num_points;
-                });
-
-                clusters.push_back({ weight / double(num_points), num_points, p.id });
-            }
-
-            tree.fill(clusters);
-        }
-    };
-
-    std::unordered_map<std::uint8_t, Zoom> zooms;
-
-    std::uint8_t limitZoom(std::uint8_t z) {
-        if (z < options.minZoom)
-            return options.minZoom;
-        if (z > options.maxZoom + 1)
-            return options.maxZoom + 1;
-        return z;
-    }
-
-    static point<double> project(const GeoJSONPoint &p) {
-        auto lngX = p.x / 360 + 0.5;
-        const double sine = std::sin(p.y * M_PI / 180);
-        const double y = 0.5 - 0.25 * std::log((1 + sine) / (1 - sine)) / M_PI;
-        auto latY = std::min(std::max(y, 0.0), 1.0);
-        return { lngX, latY };
-    }
-};
-
-} // namespace supercluster
-} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/supercluster/0.5.0/LICENSE b/src/3rdparty/mapbox-gl-native/deps/supercluster/0.5.0/LICENSE
new file mode 100644
index 000000000..14101c25a
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/supercluster/0.5.0/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2016, Mapbox
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/3rdparty/mapbox-gl-native/deps/supercluster/0.5.0/include/supercluster.hpp b/src/3rdparty/mapbox-gl-native/deps/supercluster/0.5.0/include/supercluster.hpp
new file mode 100644
index 000000000..0144463ca
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/supercluster/0.5.0/include/supercluster.hpp
@@ -0,0 +1,446 @@
+#pragma once
+
+#include <kdbush.hpp>
+#include <mapbox/feature.hpp>
+#include <mapbox/geometry/point_arithmetic.hpp>
+
+#include <algorithm>
+#include <cmath>
+#include <cstdint>
+#include <functional>
+#include <iomanip>
+#include <memory>
+#include <sstream>
+#include <vector>
+
+#ifdef DEBUG_TIMER
+#include <chrono>
+#include <iostream>
+#endif
+
+namespace mapbox {
+namespace supercluster {
+
+using namespace mapbox::geometry;
+using namespace mapbox::feature;
+
+class Cluster {
+public:
+    const point<double> pos;
+    const std::uint32_t num_points;
+    std::uint32_t id;
+    std::uint32_t parent_id = 0;
+    bool visited = false;
+    std::unique_ptr<property_map> properties{ nullptr };
+
+    Cluster(const point<double> &pos_, const std::uint32_t num_points_, const std::uint32_t id_)
+        : pos(pos_), num_points(num_points_), id(id_) {
+    }
+
+    Cluster(const point<double> &pos_,
+            const std::uint32_t num_points_,
+            const std::uint32_t id_,
+            const property_map &properties_)
+        : pos(pos_), num_points(num_points_), id(id_) {
+        if (!properties_.empty()) {
+            properties = std::make_unique<property_map>(properties_);
+        }
+    }
+
+    mapbox::feature::feature<double> toGeoJSON() const {
+        const double x = (pos.x - 0.5) * 360.0;
+        const double y =
+            360.0 * std::atan(std::exp((180.0 - pos.y * 360.0) * M_PI / 180)) / M_PI - 90.0;
+        return { point<double>{ x, y }, getProperties(),
+                 identifier(static_cast<std::uint64_t>(id)) };
+    }
+
+    property_map getProperties() const {
+        property_map result{ { "cluster", true },
+                             { "cluster_id", static_cast<std::uint64_t>(id) },
+                             { "point_count", static_cast<std::uint64_t>(num_points) } };
+        std::stringstream ss;
+        if (num_points >= 1000) {
+            ss << std::fixed;
+            if (num_points < 10000) {
+                ss << std::setprecision(1);
+            }
+            ss << double(num_points) / 1000 << "k";
+        } else {
+            ss << num_points;
+        }
+        result.emplace("point_count_abbreviated", ss.str());
+        if (properties) {
+            for (const auto &property : *properties) {
+                result.emplace(property);
+            }
+        }
+        return result;
+    }
+};
+
+} // namespace supercluster
+} // namespace mapbox
+
+namespace kdbush {
+
+using Cluster = mapbox::supercluster::Cluster;
+
+template <>
+struct nth<0, Cluster> {
+    inline static double get(const Cluster &c) {
+        return c.pos.x;
+    };
+};
+template <>
+struct nth<1, Cluster> {
+    inline static double get(const Cluster &c) {
+        return c.pos.y;
+    };
+};
+
+} // namespace kdbush
+
+namespace mapbox {
+namespace supercluster {
+
+#ifdef DEBUG_TIMER
+class Timer {
+public:
+    std::chrono::high_resolution_clock::time_point started;
+    Timer() {
+        started = std::chrono::high_resolution_clock::now();
+    }
+    void operator()(std::string msg) {
+        const auto now = std::chrono::high_resolution_clock::now();
+        const auto ms = std::chrono::duration_cast<std::chrono::microseconds>(now - started);
+        std::cerr << msg << ": " << double(ms.count()) / 1000 << "ms\n";
+        started = now;
+    }
+};
+#endif
+
+struct Options {
+    std::uint8_t minZoom = 0;   // min zoom to generate clusters on
+    std::uint8_t maxZoom = 16;  // max zoom level to cluster the points on
+    std::uint16_t radius = 40;  // cluster radius in pixels
+    std::uint16_t extent = 512; // tile extent (radius is calculated relative to it)
+    std::size_t minPoints = 2;  // minimum points to form a cluster
+    bool generateId = false;    // whether to generate numeric ids for input features (in vector tiles)
+
+    std::function<property_map(const property_map &)> map =
+        [](const property_map &p) -> property_map { return p; };
+    std::function<void(property_map &, const property_map &)> reduce{ nullptr };
+};
+
+class Supercluster {
+    using GeoJSONPoint = point<double>;
+    using GeoJSONFeature = mapbox::feature::feature<double>;
+    using GeoJSONFeatures = feature_collection<double>;
+
+    using TilePoint = point<std::int16_t>;
+    using TileFeature = mapbox::feature::feature<std::int16_t>;
+    using TileFeatures = feature_collection<std::int16_t>;
+
+public:
+    const GeoJSONFeatures features;
+    const Options options;
+
+    Supercluster(const GeoJSONFeatures &features_, Options options_ = Options())
+        : features(features_), options(std::move(options_)) {
+
+#ifdef DEBUG_TIMER
+        Timer timer;
+#endif
+        // convert and index initial points
+        zooms.emplace(options.maxZoom + 1, Zoom(features, options));
+#ifdef DEBUG_TIMER
+        timer(std::to_string(features.size()) + " initial points");
+#endif
+        for (int z = options.maxZoom; z >= options.minZoom; z--) {
+            // cluster points from the previous zoom level
+            const double r = options.radius / (options.extent * std::pow(2, z));
+            zooms.emplace(z, Zoom(zooms[z + 1], r, z, options));
+#ifdef DEBUG_TIMER
+            timer(std::to_string(zooms[z].clusters.size()) + " clusters");
+#endif
+        }
+    }
+
+    TileFeatures
+    getTile(const std::uint8_t z, const std::uint32_t x_, const std::uint32_t y) const {
+        TileFeatures result;
+
+        const auto zoom_iter = zooms.find(limitZoom(z));
+        assert(zoom_iter != zooms.end());
+        const auto &zoom = zoom_iter->second;
+
+        std::uint32_t z2 = std::pow(2, z);
+        const double r = static_cast<double>(options.radius) / options.extent;
+        std::int32_t x = x_;
+
+        const auto visitor = [&, this](const auto &id) {
+            assert(id < zoom.clusters.size());
+            const auto &c = zoom.clusters[id];
+
+            const TilePoint point(::round(this->options.extent * (c.pos.x * z2 - x)),
+                                  ::round(this->options.extent * (c.pos.y * z2 - y)));
+
+            if (c.num_points == 1) {
+                const auto &original_feature = this->features[c.id];
+                // Generate feature id if options.generateId is set.
+                auto featureId = options.generateId ? identifier{static_cast<std::uint64_t>(c.id)} : original_feature.id;
+                result.emplace_back(point, original_feature.properties, std::move(featureId));
+            } else {
+                result.emplace_back(point, c.getProperties(),
+                                    identifier(static_cast<std::uint64_t>(c.id)));
+            }
+        };
+
+        const double top = (y - r) / z2;
+        const double bottom = (y + 1 + r) / z2;
+
+        zoom.tree.range((x - r) / z2, top, (x + 1 + r) / z2, bottom, visitor);
+
+        if (x_ == 0) {
+            x = z2;
+            zoom.tree.range(1 - r / z2, top, 1, bottom, visitor);
+        }
+        if (x_ == z2 - 1) {
+            x = -1;
+            zoom.tree.range(0, top, r / z2, bottom, visitor);
+        }
+
+        return result;
+    }
+
+    GeoJSONFeatures getChildren(const std::uint32_t cluster_id) const {
+        GeoJSONFeatures children;
+        eachChild(cluster_id,
+                  [&, this](const auto &c) { children.push_back(this->clusterToGeoJSON(c)); });
+        return children;
+    }
+
+    GeoJSONFeatures getLeaves(const std::uint32_t cluster_id,
+                              const std::uint32_t limit = 10,
+                              const std::uint32_t offset = 0) const {
+        GeoJSONFeatures leaves;
+        std::uint32_t skipped = 0;
+        std::uint32_t limit_ = limit;
+        eachLeaf(cluster_id, limit_, offset, skipped,
+                 [&, this](const auto &c) { leaves.push_back(this->clusterToGeoJSON(c)); });
+        return leaves;
+    }
+
+    std::uint8_t getClusterExpansionZoom(std::uint32_t cluster_id) const {
+        auto cluster_zoom = (cluster_id % 32) - 1;
+        while (cluster_zoom <= options.maxZoom) {
+            std::uint32_t num_children = 0;
+
+            eachChild(cluster_id, [&](const auto &c) {
+                num_children++;
+                cluster_id = c.id;
+            });
+
+            cluster_zoom++;
+
+            if (num_children != 1)
+                break;
+        }
+        return cluster_zoom;
+    }
+
+private:
+    struct Zoom {
+        kdbush::KDBush<Cluster, std::uint32_t> tree;
+        std::vector<Cluster> clusters;
+
+        Zoom() = default;
+
+        Zoom(const GeoJSONFeatures &features_, const Options &options_) {
+            // generate a cluster object for each point
+            std::uint32_t i = 0;
+            clusters.reserve(features_.size());
+            for (const auto &f : features_) {
+                if (options_.reduce) {
+                    const auto clusterProperties = options_.map(f.properties);
+                    clusters.emplace_back(project(f.geometry.get<GeoJSONPoint>()), 1, i++,
+                                          clusterProperties);
+                } else {
+                    clusters.emplace_back(project(f.geometry.get<GeoJSONPoint>()), 1, i++);
+                }
+            }
+            tree.fill(clusters);
+        }
+
+        Zoom(Zoom &previous, const double r, const std::uint8_t zoom, const Options &options_) {
+
+            // The zoom parameter is restricted to [minZoom, maxZoom] by caller
+            assert(((zoom + 1) & 0b11111) == (zoom + 1));
+
+            // Since point index is encoded in the upper 27 bits, clamp the count of clusters
+            const auto previous_clusters_size = std::min(
+                previous.clusters.size(), static_cast<std::vector<Cluster>::size_type>(0x7ffffff));
+
+            for (std::size_t i = 0; i < previous_clusters_size; i++) {
+                auto &p = previous.clusters[i];
+
+                if (p.visited) {
+                    continue;
+                }
+
+                p.visited = true;
+
+                const auto num_points_origin = p.num_points;
+                auto num_points = num_points_origin;
+                auto cluster_size = previous.clusters.size();
+                // count the number of points in a potential cluster
+                previous.tree.within(p.pos.x, p.pos.y, r, [&](const auto &neighbor_id) {
+                    assert(neighbor_id < cluster_size);
+                    const auto &b = previous.clusters[neighbor_id];
+                    // filter out neighbors that are already processed
+                    if (!b.visited) {
+                        num_points += b.num_points;
+                    }
+                });
+
+                auto clusterProperties = p.properties ? *p.properties : property_map{};
+                if (num_points >= options_.minPoints) { // enough points to form a cluster
+                    point<double> weight = p.pos * double(num_points_origin);
+                    std::uint32_t id = static_cast<std::uint32_t>((i << 5) + (zoom + 1));
+
+                    // find all nearby points
+                    previous.tree.within(p.pos.x, p.pos.y, r, [&](const auto &neighbor_id) {
+                        assert(neighbor_id < cluster_size);
+                        auto &b = previous.clusters[neighbor_id];
+
+                        // filter out neighbors that are already processed
+                        if (b.visited) {
+                            return;
+                        }
+
+                        b.visited = true;
+                        b.parent_id = id;
+
+                        // accumulate coordinates for calculating weighted center
+                        weight += b.pos * double(b.num_points);
+
+                        if (options_.reduce && b.properties) {
+                            // apply reduce function to update clusterProperites
+                            options_.reduce(clusterProperties, *b.properties);
+                        }
+                    });
+                    p.parent_id = id;
+                    clusters.emplace_back(weight / double(num_points), num_points, id,
+                                          clusterProperties);
+                } else {
+                    clusters.emplace_back(p.pos, 1, p.id, clusterProperties);
+                    if (num_points > 1) {
+                        previous.tree.within(p.pos.x, p.pos.y, r, [&](const auto &neighbor_id) {
+                            assert(neighbor_id < cluster_size);
+                            auto &b = previous.clusters[neighbor_id];
+                            // filter out neighbors that are already processed
+                            if (b.visited) {
+                                return;
+                            }
+                            b.visited = true;
+                            clusters.emplace_back(b.pos, 1, b.id,
+                                                  b.properties ? *b.properties : property_map{});
+                        });
+                    }
+                }
+            }
+
+            tree.fill(clusters);
+        }
+    };
+
+    std::unordered_map<std::uint8_t, Zoom> zooms;
+
+    std::uint8_t limitZoom(const std::uint8_t z) const {
+        if (z < options.minZoom)
+            return options.minZoom;
+        if (z > options.maxZoom + 1)
+            return options.maxZoom + 1;
+        return z;
+    }
+
+    template <typename TVisitor>
+    void eachChild(const std::uint32_t cluster_id, const TVisitor &visitor) const {
+        const auto origin_id = cluster_id >> 5;
+        const auto origin_zoom = cluster_id % 32;
+
+        const auto zoom_iter = zooms.find(origin_zoom);
+        if (zoom_iter == zooms.end()) {
+            throw std::runtime_error("No cluster with the specified id.");
+        }
+
+        auto &zoom = zoom_iter->second;
+        if (origin_id >= zoom.clusters.size()) {
+            throw std::runtime_error("No cluster with the specified id.");
+        }
+
+        const double r = options.radius / (double(options.extent) * std::pow(2, origin_zoom - 1));
+        const auto &origin = zoom.clusters[origin_id];
+
+        bool hasChildren = false;
+
+        zoom.tree.within(origin.pos.x, origin.pos.y, r, [&](const auto &id) {
+            assert(id < zoom.clusters.size());
+            const auto &cluster_child = zoom.clusters[id];
+            if (cluster_child.parent_id == cluster_id) {
+                visitor(cluster_child);
+                hasChildren = true;
+            }
+        });
+
+        if (!hasChildren) {
+            throw std::runtime_error("No cluster with the specified id.");
+        }
+    }
+
+    template <typename TVisitor>
+    void eachLeaf(const std::uint32_t cluster_id,
+                  std::uint32_t &limit,
+                  const std::uint32_t offset,
+                  std::uint32_t &skipped,
+                  const TVisitor &visitor) const {
+
+        eachChild(cluster_id, [&, this](const auto &cluster_leaf) {
+            if (limit == 0)
+                return;
+            if (cluster_leaf.num_points > 1) {
+                if (skipped + cluster_leaf.num_points <= offset) {
+                    // skip the whole cluster
+                    skipped += cluster_leaf.num_points;
+                } else {
+                    // enter the cluster
+                    this->eachLeaf(cluster_leaf.id, limit, offset, skipped, visitor);
+                    // exit the cluster
+                }
+            } else if (skipped < offset) {
+                // skip a single point
+                skipped++;
+            } else {
+                // visit a single point
+                visitor(cluster_leaf);
+                limit--;
+            }
+        });
+    }
+
+    GeoJSONFeature clusterToGeoJSON(const Cluster &c) const {
+        return c.num_points == 1 ? features[c.id] : c.toGeoJSON();
+    }
+
+    static point<double> project(const GeoJSONPoint &p) {
+        const auto lngX = p.x / 360 + 0.5;
+        const double sine = std::sin(p.y * M_PI / 180);
+        const double y = 0.5 - 0.25 * std::log((1 + sine) / (1 - sine)) / M_PI;
+        const auto latY = std::min(std::max(y, 0.0), 1.0);
+        return { lngX, latY };
+    }
+};
+
+} // namespace supercluster
+} // namespace mapbox
diff --git a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile.hpp b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile.hpp
deleted file mode 100644
index 5ddae485f..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile.hpp
+++ /dev/null
@@ -1,455 +0,0 @@
-#pragma once
-
-#include "vector_tile/vector_tile_config.hpp"
-#include <mapbox/geometry.hpp>
-#include <protozero/pbf_reader.hpp>
-
-#include <cmath>
-#include <cstdint>
-#include <map>
-#include <functional> // reference_wrapper
-#include <string>
-#include <stdexcept>
-
-#include <experimental/optional>
-
-template <typename T>
-using optional = std::experimental::optional<T>;
-
-namespace mapbox { namespace vector_tile {
-
-using point_type = mapbox::geometry::point<std::int16_t>;
-
-class points_array_type : public std::vector<point_type> {
-public:
-    using coordinate_type = point_type::coordinate_type;
-    template <class... Args>
-    points_array_type(Args&&... args) : std::vector<point_type>(std::forward<Args>(args)...) {}
-};
-
-class points_arrays_type : public std::vector<points_array_type> {
-public:
-    using coordinate_type = points_array_type::coordinate_type;
-    template <class... Args>
-    points_arrays_type(Args&&... args) : std::vector<points_array_type>(std::forward<Args>(args)...) {}
-};
-
-class layer;
-
-class feature {
-public:
-    using properties_type = mapbox::geometry::property_map;
-    using packed_iterator_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
-
-    feature(protozero::data_view const&, layer const&);
-
-    GeomType getType() const { return type; }
-    optional<mapbox::geometry::value> getValue(std::string const&) const;
-    properties_type getProperties() const;
-    optional<mapbox::geometry::identifier> const& getID() const;
-    std::uint32_t getExtent() const;
-    std::uint32_t getVersion() const;
-    template <typename GeometryCollectionType>
-    GeometryCollectionType getGeometries(float scale) const;
-
-private:
-    const layer& layer_;
-    optional<mapbox::geometry::identifier> id;
-    GeomType type = GeomType::UNKNOWN;
-    packed_iterator_type tags_iter;
-    packed_iterator_type geometry_iter;
-};
-
-class layer {
-public:
-    layer(protozero::data_view const& layer_view);
-
-    std::size_t featureCount() const { return features.size(); }
-    protozero::data_view const& getFeature(std::size_t) const;
-    std::string const& getName() const;
-    std::uint32_t getExtent() const { return extent; }
-    std::uint32_t getVersion() const { return version; }
-
-private:
-    friend class feature;
-
-    std::string name;
-    std::uint32_t version;
-    std::uint32_t extent;
-    std::map<std::string, std::uint32_t> keysMap;
-    std::vector<std::reference_wrapper<const std::string>> keys;
-    std::vector<protozero::data_view> values;
-    std::vector<protozero::data_view> features;
-};
-
-class buffer {
-public:
-    buffer(std::string const& data);
-    std::vector<std::string> layerNames() const;
-    std::map<std::string, const protozero::data_view> getLayers() const { return layers; };
-    layer getLayer(const std::string&) const;
-
-private:
-    std::map<std::string, const protozero::data_view> layers;
-};
-
-static mapbox::geometry::value parseValue(protozero::data_view const& value_view) {
-    mapbox::geometry::value value;
-    protozero::pbf_reader value_reader(value_view);
-    while (value_reader.next())
-    {
-        switch (value_reader.tag()) {
-        case ValueType::STRING:
-            value = value_reader.get_string();
-            break;
-        case ValueType::FLOAT:
-            value = static_cast<double>(value_reader.get_float());
-            break;
-        case ValueType::DOUBLE:
-            value = value_reader.get_double();
-            break;
-        case ValueType::INT:
-            value = value_reader.get_int64();
-            break;
-        case ValueType::UINT:
-            value = value_reader.get_uint64();
-            break;
-        case ValueType::SINT:
-            value = value_reader.get_sint64();
-            break;
-        case ValueType::BOOL:
-            value = value_reader.get_bool();
-            break;
-        default:
-            value_reader.skip();
-            break;
-        }
-    }
-    return value;
-}
-
-inline feature::feature(protozero::data_view const& feature_view, layer const& l)
-    : layer_(l),
-      id(),
-      type(GeomType::UNKNOWN),
-      tags_iter(),
-      geometry_iter()
-    {
-    protozero::pbf_reader feature_pbf(feature_view);
-    while (feature_pbf.next()) {
-        switch (feature_pbf.tag()) {
-        case FeatureType::ID:
-            id = optional<mapbox::geometry::identifier>{ feature_pbf.get_uint64() };
-            break;
-        case FeatureType::TAGS:
-            tags_iter = feature_pbf.get_packed_uint32();
-            break;
-        case FeatureType::TYPE:
-            type = static_cast<GeomType>(feature_pbf.get_enum());
-            break;
-        case FeatureType::GEOMETRY:
-            geometry_iter = feature_pbf.get_packed_uint32();
-            break;
-        default:
-            feature_pbf.skip();
-            break;
-        }
-    }
-}
-
-inline optional<mapbox::geometry::value> feature::getValue(const std::string& key) const {
-    auto keyIter = layer_.keysMap.find(key);
-    if (keyIter == layer_.keysMap.end()) {
-        return optional<mapbox::geometry::value>();
-    }
-
-    const auto values_count = layer_.values.size();
-    const auto keymap_count = layer_.keysMap.size();
-    auto start_itr = tags_iter.begin();
-    const auto end_itr = tags_iter.end();
-    while (start_itr != end_itr) {
-        std::uint32_t tag_key = static_cast<std::uint32_t>(*start_itr++);
-
-        if (keymap_count <= tag_key) {
-            throw std::runtime_error("feature referenced out of range key");
-        }
-
-        if (start_itr == end_itr) {
-            throw std::runtime_error("uneven number of feature tag ids");
-        }
-
-        std::uint32_t tag_val = static_cast<std::uint32_t>(*start_itr++);;
-        if (values_count <= tag_val) {
-            throw std::runtime_error("feature referenced out of range value");
-        }
-
-        if (tag_key == keyIter->second) {
-            return parseValue(layer_.values[tag_val]);
-        }
-    }
-
-    return optional<mapbox::geometry::value>();
-}
-
-inline feature::properties_type feature::getProperties() const {
-    auto start_itr = tags_iter.begin();
-    const auto end_itr = tags_iter.end();
-    properties_type properties;
-    auto iter_len = std::distance(start_itr,end_itr);
-    if (iter_len > 0) {
-        properties.reserve(static_cast<std::size_t>(iter_len/2));
-        while (start_itr != end_itr) {
-            std::uint32_t tag_key = static_cast<std::uint32_t>(*start_itr++);
-            if (start_itr == end_itr) {
-                throw std::runtime_error("uneven number of feature tag ids");
-            }
-            std::uint32_t tag_val = static_cast<std::uint32_t>(*start_itr++);
-            properties.emplace(layer_.keys.at(tag_key),parseValue(layer_.values.at(tag_val)));
-        }
-    }
-    return properties;
-}
-
-inline optional<mapbox::geometry::identifier> const& feature::getID() const {
-    return id;
-}
-
-inline std::uint32_t feature::getExtent() const {
-    return layer_.getExtent();
-}
-
-inline std::uint32_t feature::getVersion() const {
-    return layer_.getVersion();
-}
-
-template <typename GeometryCollectionType>
-GeometryCollectionType feature::getGeometries(float scale) const {
-    std::uint8_t cmd = 1;
-    std::uint32_t length = 0;
-    std::int64_t x = 0;
-    std::int64_t y = 0;
-
-    GeometryCollectionType paths;
-
-    paths.emplace_back();
-
-    auto start_itr = geometry_iter.begin();
-    const auto end_itr = geometry_iter.end();
-    bool first = true;
-    std::uint32_t len_reserve = 0;
-    std::size_t extra_coords = 0;
-    if (type == GeomType::LINESTRING) {
-        extra_coords = 1;
-    } else if (type == GeomType::POLYGON) {
-        extra_coords = 2;
-    }
-    bool is_point = type == GeomType::POINT;
-
-    while (start_itr != end_itr) {
-        if (length == 0) {
-            std::uint32_t cmd_length = static_cast<std::uint32_t>(*start_itr++);
-            cmd = cmd_length & 0x7;
-            length = len_reserve = cmd_length >> 3;
-            // Prevents the creation of vector tiles that would cause
-            // a denial of service from massive over allocation. Protection
-            // limit is based on the assumption of an int64_t point which is
-            // 16 bytes in size and wanting to have a maximum of 1 MB of memory
-            // used.
-            constexpr std::uint32_t MAX_LENGTH = (1024 * 1024) / 16;
-            if (len_reserve > MAX_LENGTH) {
-                len_reserve = MAX_LENGTH;
-            }
-        }
-
-        --length;
-
-        if (cmd == CommandType::MOVE_TO || cmd == CommandType::LINE_TO) {
-
-            if (is_point) {
-                if (first && cmd == CommandType::MOVE_TO) {
-                    // note: this invalidates pointers. So we always
-                    // dynamically get the path with paths.back()
-                    paths.reserve(len_reserve);
-                    first = false;
-                }
-            } else {
-                if (first && cmd == CommandType::LINE_TO) {
-                    paths.back().reserve(len_reserve + extra_coords);
-                    first = false;
-                }
-            }
-
-            if (cmd == CommandType::MOVE_TO && !paths.back().empty()) {
-                if (paths.back().size() < paths.back().capacity()) {
-                    // Assuming we had an invalid length before
-                    // lets shrink to fit, just to make sure
-                    // we don't have a large capacity vector
-                    // just wasting memory
-                    paths.back().shrink_to_fit();
-                }
-                paths.emplace_back();
-                if (!is_point) {
-                    first = true;
-                }
-            }
-
-            x += protozero::decode_zigzag32(static_cast<std::uint32_t>(*start_itr++));
-            y += protozero::decode_zigzag32(static_cast<std::uint32_t>(*start_itr++));
-            float px = ::roundf(static_cast<float>(x) * scale);
-            float py = ::roundf(static_cast<float>(y) * scale);
-            static const float max_coord = static_cast<float>(std::numeric_limits<typename GeometryCollectionType::coordinate_type>::max());
-            static const float min_coord = static_cast<float>(std::numeric_limits<typename GeometryCollectionType::coordinate_type>::min());
-
-            if (px > max_coord ||
-                px < min_coord ||
-                py > max_coord ||
-                py < min_coord
-                ) {
-                std::runtime_error("paths outside valid range of coordinate_type");
-            } else {
-                paths.back().emplace_back(
-                    static_cast<typename GeometryCollectionType::coordinate_type>(px),
-                    static_cast<typename GeometryCollectionType::coordinate_type>(py));
-            }
-        } else if (cmd == CommandType::CLOSE) {
-            if (!paths.back().empty()) {
-                paths.back().push_back(paths.back()[0]);
-            }
-            length = 0;
-        } else {
-            throw std::runtime_error("unknown command");
-        }
-    }
-    if (paths.size() < paths.capacity()) {
-        // Assuming we had an invalid length before
-        // lets shrink to fit, just to make sure
-        // we don't have a large capacity vector
-        // just wasting memory
-        paths.shrink_to_fit();
-    }
-#if defined(DEBUG)
-    for (auto const& p : paths) {
-        assert(p.size() == p.capacity());
-    }
-#endif
-    return paths;
-}
-
-inline buffer::buffer(std::string const& data)
-    : layers() {
-        protozero::pbf_reader data_reader(data);
-        while (data_reader.next(TileType::LAYERS)) {
-            const protozero::data_view layer_view = data_reader.get_view();
-            protozero::pbf_reader layer_reader(layer_view);
-            std::string name;
-            bool has_name = false;
-            while (layer_reader.next(LayerType::NAME)) {
-                name = layer_reader.get_string();
-                has_name = true;
-            }
-            if (!has_name) {
-                throw std::runtime_error("Layer missing name");
-            }
-            layers.emplace(name, layer_view);
-        }
-}
-
-inline std::vector<std::string> buffer::layerNames() const {
-    std::vector<std::string> names;
-    names.reserve(layers.size());
-    for (auto const& layer : layers) {
-        names.emplace_back(layer.first);
-    }
-    return names;
-}
-
-inline layer buffer::getLayer(const std::string& name) const {
-    auto layer_it = layers.find(name);
-    if (layer_it == layers.end()) {
-        throw std::runtime_error(std::string("no layer by the name of '")+name+"'");
-    }
-    return layer(layer_it->second);
-}
-
-inline layer::layer(protozero::data_view const& layer_view) :
-    name(),
-    version(1),
-    extent(4096),
-    keysMap(),
-    keys(),
-    values(),
-    features()
-{
-    bool has_name = false;
-    bool has_extent = false;
-    bool has_version = false;
-    protozero::pbf_reader layer_pbf(layer_view);
-    while (layer_pbf.next()) {
-        switch (layer_pbf.tag()) {
-        case LayerType::NAME:
-            {
-                name = layer_pbf.get_string();
-                has_name = true;
-            }
-            break;
-        case LayerType::FEATURES:
-            {
-                features.push_back(layer_pbf.get_view());
-            }
-            break;
-        case LayerType::KEYS:
-            {
-                // We want to keep the keys in the order of the vector tile
-                // https://github.com/mapbox/mapbox-gl-native/pull/5183
-                auto iter = keysMap.emplace(layer_pbf.get_string(), keysMap.size());
-                keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first));
-            }
-            break;
-        case LayerType::VALUES:
-            {
-                values.emplace_back(layer_pbf.get_view());
-            }
-            break;
-        case LayerType::EXTENT:
-            {
-                extent = layer_pbf.get_uint32();
-                has_extent = true;
-            }
-            break;
-        case LayerType::VERSION:
-            {
-                version = layer_pbf.get_uint32();
-                has_version = true;
-            }
-            break;
-        default:
-            {
-                layer_pbf.skip();
-            }
-            break;
-        }
-    }
-    if (!has_version || !has_name || !has_extent) {
-        std::string msg("missing required field:");
-        if (!has_version) {
-            msg += " version ";
-        }
-        if (!has_extent) {
-            msg += " extent ";
-        }
-        if (!has_name) {
-            msg += " name";
-        }
-        throw std::runtime_error(msg.c_str());
-    }
-}
-
-inline protozero::data_view const& layer::getFeature(std::size_t i) const {
-    return features.at(i);
-}
-
-inline std::string const& layer::getName() const {
-    return name;
-}
-
-}} // namespace mapbox/vector_tile
diff --git a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile/vector_tile_config.hpp b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile/vector_tile_config.hpp
deleted file mode 100644
index acf118567..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile/vector_tile_config.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-namespace mapbox { namespace vector_tile {
-
-
-enum TileType : std::uint32_t
-{
-    LAYERS = 3
-};
-
-enum LayerType : std::uint32_t
-{
-    VERSION = 15,
-    NAME = 1,
-    FEATURES = 2,
-    KEYS = 3,
-    VALUES = 4,
-    EXTENT = 5
-};
-
-enum FeatureType : std::uint32_t
-{
-    ID = 1,
-    TAGS = 2,
-    TYPE = 3,
-    GEOMETRY = 4,
-    RASTER = 5
-};
-
-enum ValueType : std::uint32_t
-{
-    STRING = 1,
-    FLOAT = 2,
-    DOUBLE = 3,
-    INT = 4,
-    UINT = 5,
-    SINT = 6,
-    BOOL = 7
-};
-
-enum GeomType : std::uint8_t
-{
-    UNKNOWN = 0,
-    POINT = 1,
-    LINESTRING = 2,
-    POLYGON = 3
-};
-
-enum CommandType : std::uint8_t
-{
-    END = 0,
-    MOVE_TO = 1,
-    LINE_TO = 2,
-    CLOSE = 7
-};
-
-
-} }
diff --git a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile/version.hpp b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile/version.hpp
deleted file mode 100644
index cc1974d63..000000000
--- a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.2/include/mapbox/vector_tile/version.hpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-/// The major version number
-#define VECTOR_TILE_VERSION_MAJOR 1
-
-/// The minor version number
-#define VECTOR_TILE_VERSION_MINOR 0
-
-/// The patch number
-#define VECTOR_TILE_VERSION_PATCH 2
-
-/// The complete version number
-#define VECTOR_TILE_VERSION_CODE (VECTOR_TILE_VERSION_MAJOR * 10000 + VECTOR_TILE_VERSION_MINOR * 100 + VECTOR_TILE_VERSION_PATCH)
-
-/// Version number as string
-#define VECTOR_TILE_VERSION_STRING "1.0.2"
diff --git a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile.hpp b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile.hpp
new file mode 100644
index 000000000..1f3d78433
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile.hpp
@@ -0,0 +1,481 @@
+#pragma once
+
+#include "vector_tile/vector_tile_config.hpp"
+#include <mapbox/geometry.hpp>
+#include <mapbox/feature.hpp>
+#include <protozero/pbf_reader.hpp>
+
+#include <cmath>
+#include <cstdint>
+#include <map>
+#include <functional> // reference_wrapper
+#include <string>
+#include <stdexcept>
+
+namespace mapbox { namespace vector_tile {
+
+using point_type = mapbox::geometry::point<std::int16_t>;
+
+class points_array_type : public std::vector<point_type> {
+public:
+    using coordinate_type = point_type::coordinate_type;
+    template <class... Args>
+    points_array_type(Args&&... args) : std::vector<point_type>(std::forward<Args>(args)...) {}
+};
+
+class points_arrays_type : public std::vector<points_array_type> {
+public:
+    using coordinate_type = points_array_type::coordinate_type;
+    template <class... Args>
+    points_arrays_type(Args&&... args) : std::vector<points_array_type>(std::forward<Args>(args)...) {}
+};
+
+class layer;
+
+class feature {
+public:
+    using properties_type = mapbox::feature::property_map;
+    using packed_iterator_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
+
+    feature(protozero::data_view const&, layer const&);
+
+    GeomType getType() const { return type; }
+    /**
+     * Retrieve the value associated with a given key from the feature.
+     *
+     * @param key The key used to look up the corresponding value.
+     * @param warning  A pointer to a string that may be used to record any warnings that
+ *                     occur during the lookup process.
+     *                 The caller is responsible for managing the memory of this string.
+     * @return The value associated with the specified key, or a null value if the key is not found.
+     *
+     * Note: If the lookup process encounters a duplicate key in the feature, the function will
+     *       return the value in the `values` set to which the associated tag index points to, and 
+     *       will append a message to the `warning` string (if provided) to alert the caller to the
+     *       presence of the duplicate key. 
+     *       The caller should ensure that the `warning` string is properly initialized
+     *       and cleaned up after use.
+     */
+    mapbox::feature::value getValue(std::string const&, std::string* warning = nullptr) const;
+    properties_type getProperties() const;
+    mapbox::feature::identifier const& getID() const;
+    std::uint32_t getExtent() const;
+    std::uint32_t getVersion() const;
+    template <typename GeometryCollectionType>
+    GeometryCollectionType getGeometries(float scale) const;
+
+private:
+    const layer& layer_;
+    mapbox::feature::identifier id;
+    GeomType type = GeomType::UNKNOWN;
+    packed_iterator_type tags_iter;
+    packed_iterator_type geometry_iter;
+};
+
+class layer {
+public:
+    layer(protozero::data_view const& layer_view);
+
+    std::size_t featureCount() const { return features.size(); }
+    protozero::data_view const& getFeature(std::size_t) const;
+    std::string const& getName() const;
+    std::uint32_t getExtent() const { return extent; }
+    std::uint32_t getVersion() const { return version; }
+
+private:
+    friend class feature;
+
+    std::string name;
+    std::uint32_t version;
+    std::uint32_t extent;
+    std::multimap<std::string, std::uint32_t> keysMap;
+    std::vector<std::reference_wrapper<const std::string>> keys;
+    std::vector<protozero::data_view> values;
+    std::vector<protozero::data_view> features;
+};
+
+class buffer {
+public:
+    buffer(std::string const& data);
+    std::vector<std::string> layerNames() const;
+    std::map<std::string, const protozero::data_view> getLayers() const { return layers; };
+    layer getLayer(const std::string&) const;
+
+private:
+    std::map<std::string, const protozero::data_view> layers;
+};
+
+static mapbox::feature::value parseValue(protozero::data_view const& value_view) {
+    mapbox::feature::value value;
+    protozero::pbf_reader value_reader(value_view);
+    while (value_reader.next())
+    {
+        switch (value_reader.tag()) {
+        case ValueType::STRING:
+            value = value_reader.get_string();
+            break;
+        case ValueType::FLOAT:
+            value = static_cast<double>(value_reader.get_float());
+            break;
+        case ValueType::DOUBLE:
+            value = value_reader.get_double();
+            break;
+        case ValueType::INT:
+            value = value_reader.get_int64();
+            break;
+        case ValueType::UINT:
+            value = value_reader.get_uint64();
+            break;
+        case ValueType::SINT:
+            value = value_reader.get_sint64();
+            break;
+        case ValueType::BOOL:
+            value = value_reader.get_bool();
+            break;
+        default:
+            value_reader.skip();
+            break;
+        }
+    }
+    return value;
+}
+
+inline feature::feature(protozero::data_view const& feature_view, layer const& l)
+    : layer_(l),
+      id(),
+      type(GeomType::UNKNOWN),
+      tags_iter(),
+      geometry_iter()
+    {
+    protozero::pbf_reader feature_pbf(feature_view);
+    while (feature_pbf.next()) {
+        switch (feature_pbf.tag()) {
+        case FeatureType::ID:
+            id = feature_pbf.get_uint64();
+            break;
+        case FeatureType::TAGS:
+            tags_iter = feature_pbf.get_packed_uint32();
+            break;
+        case FeatureType::TYPE:
+            type = static_cast<GeomType>(feature_pbf.get_enum());
+            break;
+        case FeatureType::GEOMETRY:
+            geometry_iter = feature_pbf.get_packed_uint32();
+            break;
+        default:
+            feature_pbf.skip();
+            break;
+        }
+    }
+}
+
+inline mapbox::feature::value feature::getValue(const std::string& key, std::string* warning ) const {
+    const auto key_range = layer_.keysMap.equal_range(key);
+    const auto key_count = std::distance(key_range.first, key_range.second) ;
+    if (key_count < 1) {
+        return mapbox::feature::null_value;
+    }
+
+    const auto values_count = layer_.values.size();
+    auto start_itr = tags_iter.begin();
+    const auto end_itr = tags_iter.end();
+    while (start_itr != end_itr) {
+        std::uint32_t tag_key = static_cast<std::uint32_t>(*start_itr++);
+
+        if (start_itr == end_itr) {
+            throw std::runtime_error("uneven number of feature tag ids");
+        }
+
+        std::uint32_t tag_val = static_cast<std::uint32_t>(*start_itr++);;
+        if (values_count <= tag_val) {
+            throw std::runtime_error("feature referenced out of range value");
+        }
+
+        bool key_found = false;
+        for (auto i = key_range.first; i != key_range.second; ++i) {
+            if (i->second == tag_key) {
+                key_found = true;
+                break;
+            }
+        }
+
+        if (key_found) {
+            // Continue process with case when same keys having multiple tag ids.
+            if (key_count > 1 && warning) {
+                *warning = std::string("duplicate keys with different tag ids are found");
+            }
+            return parseValue(layer_.values[tag_val]);
+        }
+    }
+
+    return mapbox::feature::null_value;
+}
+
+inline feature::properties_type feature::getProperties() const {
+    auto start_itr = tags_iter.begin();
+    const auto end_itr = tags_iter.end();
+    properties_type properties;
+    auto iter_len = std::distance(start_itr,end_itr);
+    if (iter_len > 0) {
+        properties.reserve(static_cast<std::size_t>(iter_len/2));
+        while (start_itr != end_itr) {
+            std::uint32_t tag_key = static_cast<std::uint32_t>(*start_itr++);
+            if (start_itr == end_itr) {
+                throw std::runtime_error("uneven number of feature tag ids");
+            }
+            std::uint32_t tag_val = static_cast<std::uint32_t>(*start_itr++);
+            properties.emplace(layer_.keys.at(tag_key),parseValue(layer_.values.at(tag_val)));
+        }
+    }
+    return properties;
+}
+
+inline mapbox::feature::identifier const& feature::getID() const {
+    return id;
+}
+
+inline std::uint32_t feature::getExtent() const {
+    return layer_.getExtent();
+}
+
+inline std::uint32_t feature::getVersion() const {
+    return layer_.getVersion();
+}
+
+template <typename GeometryCollectionType>
+GeometryCollectionType feature::getGeometries(float scale) const {
+    std::uint8_t cmd = 1;
+    std::uint32_t length = 0;
+    std::int64_t x = 0;
+    std::int64_t y = 0;
+
+    GeometryCollectionType paths;
+
+    paths.emplace_back();
+
+    auto start_itr = geometry_iter.begin();
+    const auto end_itr = geometry_iter.end();
+    bool first = true;
+    std::uint32_t len_reserve = 0;
+    std::size_t extra_coords = 0;
+    if (type == GeomType::LINESTRING) {
+        extra_coords = 1;
+    } else if (type == GeomType::POLYGON) {
+        extra_coords = 2;
+    }
+    bool is_point = type == GeomType::POINT;
+
+    while (start_itr != end_itr) {
+        if (length == 0) {
+            std::uint32_t cmd_length = static_cast<std::uint32_t>(*start_itr++);
+            cmd = cmd_length & 0x7;
+            length = len_reserve = cmd_length >> 3;
+            // Prevents the creation of vector tiles that would cause
+            // a denial of service from massive over allocation. Protection
+            // limit is based on the assumption of an int64_t point which is
+            // 16 bytes in size and wanting to have a maximum of 1 MB of memory
+            // used.
+            constexpr std::uint32_t MAX_LENGTH = (1024 * 1024) / 16;
+            if (len_reserve > MAX_LENGTH) {
+                len_reserve = MAX_LENGTH;
+            }
+        }
+
+        if (cmd == CommandType::MOVE_TO || cmd == CommandType::LINE_TO) {
+            if (length == 0) {
+                // If length is still equal to zero after the preceding step, this
+                // represents a command with an invalid command count, so we continue here to
+                // exit appropriately rather than underflow when we decrement length
+                continue;
+            }
+
+            --length;
+
+            if (is_point) {
+                if (first && cmd == CommandType::MOVE_TO) {
+                    // note: this invalidates pointers. So we always
+                    // dynamically get the path with paths.back()
+                    paths.reserve(len_reserve);
+                    first = false;
+                }
+            } else {
+                if (first && cmd == CommandType::LINE_TO) {
+                    paths.back().reserve(len_reserve + extra_coords);
+                    first = false;
+                }
+            }
+
+            if (cmd == CommandType::MOVE_TO && !paths.back().empty()) {
+                if (paths.back().size() < paths.back().capacity()) {
+                    // Assuming we had an invalid length before
+                    // lets shrink to fit, just to make sure
+                    // we don't have a large capacity vector
+                    // just wasting memory
+                    paths.back().shrink_to_fit();
+                }
+                paths.emplace_back();
+                if (!is_point) {
+                    first = true;
+                }
+            }
+
+            x += protozero::decode_zigzag32(static_cast<std::uint32_t>(*start_itr++));
+            y += protozero::decode_zigzag32(static_cast<std::uint32_t>(*start_itr++));
+            float px = ::roundf(static_cast<float>(x) * scale);
+            float py = ::roundf(static_cast<float>(y) * scale);
+            static const float max_coord = static_cast<float>(std::numeric_limits<typename GeometryCollectionType::coordinate_type>::max());
+            static const float min_coord = static_cast<float>(std::numeric_limits<typename GeometryCollectionType::coordinate_type>::min());
+
+            if (px > max_coord ||
+                px < min_coord ||
+                py > max_coord ||
+                py < min_coord
+                ) {
+                throw std::runtime_error("paths outside valid range of coordinate_type");
+            } else {
+                paths.back().emplace_back(
+                    static_cast<typename GeometryCollectionType::coordinate_type>(px),
+                    static_cast<typename GeometryCollectionType::coordinate_type>(py));
+            }
+        } else if (cmd == CommandType::CLOSE) {
+            if (!paths.back().empty()) {
+                paths.back().push_back(paths.back()[0]);
+            }
+            length = 0;
+        } else {
+            throw std::runtime_error("unknown command");
+        }
+    }
+    if (paths.size() < paths.capacity()) {
+        // Assuming we had an invalid length before
+        // lets shrink to fit, just to make sure
+        // we don't have a large capacity vector
+        // just wasting memory
+        paths.shrink_to_fit();
+    }
+#if defined(DEBUG)
+    for (auto const& p : paths) {
+        assert(p.size() == p.capacity());
+    }
+#endif
+    return paths;
+}
+
+inline buffer::buffer(std::string const& data)
+    : layers() {
+        protozero::pbf_reader data_reader(data);
+        while (data_reader.next(TileType::LAYERS)) {
+            const protozero::data_view layer_view = data_reader.get_view();
+            protozero::pbf_reader layer_reader(layer_view);
+            std::string name;
+            bool has_name = false;
+            while (layer_reader.next(LayerType::NAME)) {
+                name = layer_reader.get_string();
+                has_name = true;
+            }
+            if (!has_name) {
+                throw std::runtime_error("Layer missing name");
+            }
+            layers.emplace(name, layer_view);
+        }
+}
+
+inline std::vector<std::string> buffer::layerNames() const {
+    std::vector<std::string> names;
+    names.reserve(layers.size());
+    for (auto const& layer : layers) {
+        names.emplace_back(layer.first);
+    }
+    return names;
+}
+
+inline layer buffer::getLayer(const std::string& name) const {
+    auto layer_it = layers.find(name);
+    if (layer_it == layers.end()) {
+        throw std::runtime_error(std::string("no layer by the name of '")+name+"'");
+    }
+    return layer(layer_it->second);
+}
+
+inline layer::layer(protozero::data_view const& layer_view) :
+    name(),
+    version(1),
+    extent(4096),
+    keysMap(),
+    keys(),
+    values(),
+    features()
+{
+    bool has_name = false;
+    bool has_extent = false;
+    bool has_version = false;
+    protozero::pbf_reader layer_pbf(layer_view);
+    while (layer_pbf.next()) {
+        switch (layer_pbf.tag()) {
+        case LayerType::NAME:
+            {
+                name = layer_pbf.get_string();
+                has_name = true;
+            }
+            break;
+        case LayerType::FEATURES:
+            {
+                features.push_back(layer_pbf.get_view());
+            }
+            break;
+        case LayerType::KEYS:
+            {
+                // We want to keep the keys in the order of the vector tile
+                // https://github.com/mapbox/mapbox-gl-native/pull/5183
+                auto iter = keysMap.emplace(layer_pbf.get_string(), keys.size());
+                keys.emplace_back(std::reference_wrapper<const std::string>(iter->first));
+            }
+            break;
+        case LayerType::VALUES:
+            {
+                values.emplace_back(layer_pbf.get_view());
+            }
+            break;
+        case LayerType::EXTENT:
+            {
+                extent = layer_pbf.get_uint32();
+                has_extent = true;
+            }
+            break;
+        case LayerType::VERSION:
+            {
+                version = layer_pbf.get_uint32();
+                has_version = true;
+            }
+            break;
+        default:
+            {
+                layer_pbf.skip();
+            }
+            break;
+        }
+    }
+    if (!has_version || !has_name || !has_extent) {
+        std::string msg("missing required field:");
+        if (!has_version) {
+            msg += " version ";
+        }
+        if (!has_extent) {
+            msg += " extent ";
+        }
+        if (!has_name) {
+            msg += " name";
+        }
+        throw std::runtime_error(msg.c_str());
+    }
+}
+
+inline protozero::data_view const& layer::getFeature(std::size_t i) const {
+    return features.at(i);
+}
+
+inline std::string const& layer::getName() const {
+    return name;
+}
+
+}} // namespace mapbox/vector_tile
diff --git a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile/vector_tile_config.hpp b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile/vector_tile_config.hpp
new file mode 100644
index 000000000..acf118567
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile/vector_tile_config.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <cstdint>
+
+namespace mapbox { namespace vector_tile {
+
+
+enum TileType : std::uint32_t
+{
+    LAYERS = 3
+};
+
+enum LayerType : std::uint32_t
+{
+    VERSION = 15,
+    NAME = 1,
+    FEATURES = 2,
+    KEYS = 3,
+    VALUES = 4,
+    EXTENT = 5
+};
+
+enum FeatureType : std::uint32_t
+{
+    ID = 1,
+    TAGS = 2,
+    TYPE = 3,
+    GEOMETRY = 4,
+    RASTER = 5
+};
+
+enum ValueType : std::uint32_t
+{
+    STRING = 1,
+    FLOAT = 2,
+    DOUBLE = 3,
+    INT = 4,
+    UINT = 5,
+    SINT = 6,
+    BOOL = 7
+};
+
+enum GeomType : std::uint8_t
+{
+    UNKNOWN = 0,
+    POINT = 1,
+    LINESTRING = 2,
+    POLYGON = 3
+};
+
+enum CommandType : std::uint8_t
+{
+    END = 0,
+    MOVE_TO = 1,
+    LINE_TO = 2,
+    CLOSE = 7
+};
+
+
+} }
diff --git a/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile/version.hpp b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile/version.hpp
new file mode 100644
index 000000000..f5f8e0413
--- /dev/null
+++ b/src/3rdparty/mapbox-gl-native/deps/vector-tile/1.0.4/include/mapbox/vector_tile/version.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+/// The major version number
+#define VECTOR_TILE_VERSION_MAJOR 1
+
+/// The minor version number
+#define VECTOR_TILE_VERSION_MINOR 0
+
+/// The patch number
+#define VECTOR_TILE_VERSION_PATCH 4
+
+/// The complete version number
+#define VECTOR_TILE_VERSION_CODE (VECTOR_TILE_VERSION_MAJOR * 10000 + VECTOR_TILE_VERSION_MINOR * 100 + VECTOR_TILE_VERSION_PATCH)
+
+/// Version number as string
+#define VECTOR_TILE_VERSION_STRING "1.0.4"
diff --git a/src/3rdparty/mapbox-gl-native/include/mbgl/annotation/annotation.hpp b/src/3rdparty/mapbox-gl-native/include/mbgl/annotation/annotation.hpp
index bbe479b5b..843401372 100644
--- a/src/3rdparty/mapbox-gl-native/include/mbgl/annotation/annotation.hpp
+++ b/src/3rdparty/mapbox-gl-native/include/mbgl/annotation/annotation.hpp
@@ -12,7 +12,7 @@
 
 namespace mbgl {
 
-using AnnotationID = uint32_t;
+using AnnotationID = uint64_t;
 using AnnotationIDs = std::vector<AnnotationID>;
 
 class SymbolAnnotation {
diff --git a/src/3rdparty/mapbox-gl-native/include/mbgl/util/feature.hpp b/src/3rdparty/mapbox-gl-native/include/mbgl/util/feature.hpp
index 4eeceda94..9e2286018 100644
--- a/src/3rdparty/mapbox-gl-native/include/mbgl/util/feature.hpp
+++ b/src/3rdparty/mapbox-gl-native/include/mbgl/util/feature.hpp
@@ -2,15 +2,15 @@
 
 #include <mbgl/util/optional.hpp>
 
-#include <mapbox/geometry/feature.hpp>
+#include <mapbox/feature.hpp>
 
 namespace mbgl {
 
-using Value = mapbox::geometry::value;
-using NullValue = mapbox::geometry::null_value_t;
-using PropertyMap = mapbox::geometry::property_map;
-using FeatureIdentifier = mapbox::geometry::identifier;
-using Feature = mapbox::geometry::feature<double>;
+using Value = mapbox::feature::value;
+using NullValue = mapbox::feature::null_value_t;
+using PropertyMap = mapbox::feature::property_map;
+using FeatureIdentifier = mapbox::feature::identifier;
+using Feature = mapbox::feature::feature<double>;
 
 template <class T>
 optional<T> numericValue(const Value& value) {
diff --git a/src/3rdparty/mapbox-gl-native/include/mbgl/util/geometry.hpp b/src/3rdparty/mapbox-gl-native/include/mbgl/util/geometry.hpp
index 283ec7dbb..6bdd01fb7 100644
--- a/src/3rdparty/mapbox-gl-native/include/mbgl/util/geometry.hpp
+++ b/src/3rdparty/mapbox-gl-native/include/mbgl/util/geometry.hpp
@@ -15,6 +15,8 @@ enum class FeatureType : uint8_t {
     Polygon = 3
 };
 
+using EmptyGeometry = mapbox::geometry::empty;
+
 template <class T>
 using Point = mapbox::geometry::point<T>;
 
@@ -45,6 +47,7 @@ Point<S> convertPoint(const Point<T>& p) {
 }
 
 struct ToFeatureType {
+    FeatureType operator()(const EmptyGeometry&) const { return FeatureType::Unknown; }
     template <class T>
     FeatureType operator()(const Point<T> &) const { return FeatureType::Point; }
     template <class T>
diff --git a/src/3rdparty/mapbox-gl-native/mapbox-gl-native.pro b/src/3rdparty/mapbox-gl-native/mapbox-gl-native.pro
index 4d5835d73..2665d7dc5 100644
--- a/src/3rdparty/mapbox-gl-native/mapbox-gl-native.pro
+++ b/src/3rdparty/mapbox-gl-native/mapbox-gl-native.pro
@@ -409,14 +409,14 @@ INCLUDEPATH += \
     deps/boost/1.65.1/include \
     deps/earcut/0.12.4 \
     deps/earcut/0.12.4/include \
-    deps/geojson/0.4.2 \
-    deps/geojson/0.4.2/include \
-    deps/geojsonvt/6.5.1 \
-    deps/geojsonvt/6.5.1/include \
+    deps/geojson/0.5.1 \
+    deps/geojson/0.5.1/include \
+    deps/geojsonvt/6.6.5 \
+    deps/geojsonvt/6.6.5/include \
     deps/geometry/0.9.3 \
     deps/geometry/0.9.3/include \
-    deps/kdbush/0.1.1-1 \
-    deps/kdbush/0.1.1-1/include \
+    deps/kdbush/0.1.3 \
+    deps/kdbush/0.1.3/include \
     deps/optional/f27e7908 \
     deps/optional/f27e7908/include \
     deps/polylabel/1.0.3 \
@@ -427,16 +427,16 @@ INCLUDEPATH += \
     deps/rapidjson/1.1.0/include \
     deps/shelf-pack/2.1.1 \
     deps/shelf-pack/2.1.1/include \
-    deps/supercluster/0.2.2 \
-    deps/supercluster/0.2.2/include \
+    deps/supercluster/0.5.0 \
+    deps/supercluster/0.5.0/include \
     deps/tao_tuple/28626e99 \
     deps/tao_tuple/28626e99/include \
     deps/unique_resource/cba309e \
     deps/unique_resource/cba309e/include \
     deps/variant/1.1.4 \
     deps/variant/1.1.4/include \
-    deps/vector-tile/1.0.2 \
-    deps/vector-tile/1.0.2/include \
+    deps/vector-tile/1.0.4 \
+    deps/vector-tile/1.0.4/include \
     deps/wagyu/0.4.3 \
     deps/wagyu/0.4.3/include \
     include \
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.cpp
index d405418a4..e5e3b68df 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.cpp
@@ -55,8 +55,8 @@ optional<Value> AnnotationTileFeature::getValue(const std::string& key) const {
     return optional<Value>();
 }
 
-optional<FeatureIdentifier> AnnotationTileFeature::getID() const {
-    return { static_cast<uint64_t>(data->id) };
+FeatureIdentifier AnnotationTileFeature::getID() const {
+    return data->id;
 }
 
 GeometryCollection AnnotationTileFeature::getGeometries() const {
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.hpp
index a4d1e6680..1e23fdf98 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/annotation_tile.hpp
@@ -27,7 +27,7 @@ public:
 
     FeatureType getType() const override;
     optional<Value> getValue(const std::string&) const override;
-    optional<FeatureIdentifier> getID() const override;
+    FeatureIdentifier getID() const override;
     GeometryCollection getGeometries() const override;
 
 private:
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/shape_annotation_impl.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/shape_annotation_impl.cpp
index 715dce484..728766dce 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/shape_annotation_impl.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/annotation/shape_annotation_impl.cpp
@@ -22,7 +22,7 @@ void ShapeAnnotationImpl::updateTileData(const CanonicalTileID& tileID, Annotati
     static const double baseTolerance = 4;
 
     if (!shapeTiler) {
-        mapbox::geometry::feature_collection<double> features;
+        mapbox::feature::feature_collection<double> features;
         features.emplace_back(ShapeAnnotationGeometry::visit(geometry(), [] (auto&& geom) {
             return Feature { std::move(geom) };
         }));
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/layout/symbol_feature.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/layout/symbol_feature.hpp
index f4dc1680b..e6a40ab1e 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/layout/symbol_feature.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/layout/symbol_feature.hpp
@@ -18,7 +18,7 @@ public:
     FeatureType getType() const override { return feature->getType(); }
     optional<Value> getValue(const std::string& key) const override { return feature->getValue(key); };
     std::unordered_map<std::string,Value> getProperties() const override { return feature->getProperties(); };
-    optional<FeatureIdentifier> getID() const override { return feature->getID(); };
+    FeatureIdentifier getID() const override { return feature->getID(); };
     GeometryCollection getGeometries() const override { return geometry; };
 
     std::unique_ptr<GeometryTileFeature> feature;
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/renderer/renderer.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/renderer/renderer.cpp
index 1d2f2bb52..c7bd46106 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/renderer/renderer.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/renderer/renderer.cpp
@@ -75,10 +75,9 @@ AnnotationIDs Renderer::queryShapeAnnotations(const ScreenBox& box) const {
 AnnotationIDs Renderer::getAnnotationIDs(const std::vector<Feature>& features) const {
     std::set<AnnotationID> set;
     for (auto &feature : features) {
-        assert(feature.id);
-        assert(feature.id->is<uint64_t>());
-        assert(feature.id->get<uint64_t>() <= std::numeric_limits<AnnotationID>::max());
-        set.insert(static_cast<AnnotationID>(feature.id->get<uint64_t>()));
+        assert(feature.id.is<uint64_t>());
+        assert(feature.id.get<uint64_t>() <= std::numeric_limits<AnnotationID>::max());
+        set.insert(static_cast<AnnotationID>(feature.id.get<uint64_t>()));
     }
     AnnotationIDs ids;
     ids.reserve(set.size());
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/compound_expression.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/compound_expression.cpp
index 46b0c7fe1..88eaed184 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/compound_expression.cpp
@@ -221,8 +221,8 @@ static std::unique_ptr<detail::SignatureBase> makeSignature(Fn evaluateFunction,
 Value featureIdAsExpressionValue(EvaluationContext params) {
     assert(params.feature);
     auto id = params.feature->getID();
-    if (!id) return Null;
-    return id->match([](const auto& idid) {
+    if (id.is<NullValue>()) return Null;
+    return id.match([](const auto& idid) {
         return toExpressionValue(mbgl::Value(idid));
     });
 };
@@ -273,8 +273,7 @@ optional<std::string> featurePropertyAsString(EvaluationContext params, const st
 optional<double> featureIdAsDouble(EvaluationContext params) {
     assert(params.feature);
     auto id = params.feature->getID();
-    if (!id) return optional<double>();
-    return id->match(
+    return id.match(
         [](double value) { return value; },
         [](uint64_t value) { return optional<double>(static_cast<double>(value)); },
         [](int64_t value) { return optional<double>(static_cast<double>(value)); },
@@ -285,8 +284,7 @@ optional<double> featureIdAsDouble(EvaluationContext params) {
 optional<std::string> featureIdAsString(EvaluationContext params) {
     assert(params.feature);
     auto id = params.feature->getID();
-    if (!id) return optional<std::string>();
-    return id->match(
+    return id.match(
         [](std::string value) { return value; },
         [](auto) { return optional<std::string>(); }
     );
@@ -421,10 +419,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
         }
 
         auto id = params.feature->getID();
-        if (!id) {
-            return Null;
-        }
-        return id->match(
+        return id.match(
             [](const auto& idValue) {
                 return toExpressionValue(mbgl::Value(idValue));
             }
@@ -623,7 +618,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
 
     define("filter-has-id", [](const EvaluationContext& params) -> Result<bool> {
         assert(params.feature);
-        return bool(params.feature->getID());
+        return !params.feature->getID().is<NullValue>();
     });
 
     define("filter-type-in", [](const EvaluationContext& params, const Varargs<std::string>& types) -> Result<bool> {
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/expression.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/expression.cpp
index d9dbbfa1d..25a9e47d4 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/expression.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/style/expression/expression.cpp
@@ -16,7 +16,7 @@ public:
         return apply_visitor(ToFeatureType(), feature.geometry);
     }
     PropertyMap getProperties() const override { return feature.properties; }
-    optional<FeatureIdentifier> getID() const override { return feature.id; }
+    FeatureIdentifier getID() const override { return feature.id; }
     GeometryCollection getGeometries() const override { return {}; }
     optional<mbgl::Value> getValue(const std::string& key) const override {
         auto it = feature.properties.find(key);
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.cpp
index fd6d7d301..e652826e4 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -17,7 +17,7 @@ public:
                   const mapbox::geojsonvt::Options& options)
         : impl(geoJSON, options) {}
 
-    mapbox::geometry::feature_collection<int16_t> getTile(const CanonicalTileID& tileID) final {
+    mapbox::feature::feature_collection<int16_t> getTile(const CanonicalTileID& tileID) final {
         return impl.getTile(tileID.z, tileID.x, tileID.y).features;
     }
 
@@ -27,11 +27,11 @@ private:
 
 class SuperclusterData : public GeoJSONData {
 public:
-    SuperclusterData(const mapbox::geometry::feature_collection<double>& features,
+    SuperclusterData(const mapbox::feature::feature_collection<double>& features,
                      const mapbox::supercluster::Options& options)
         : impl(features, options) {}
 
-    mapbox::geometry::feature_collection<int16_t> getTile(const CanonicalTileID& tileID) final {
+    mapbox::feature::feature_collection<int16_t> getTile(const CanonicalTileID& tileID) final {
         return impl.getTile(tileID.z, tileID.x, tileID.y);
     }
 
@@ -50,14 +50,14 @@ GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
     double scale = util::EXTENT / util::tileSize;
 
     if (options.cluster
-        && geoJSON.is<mapbox::geometry::feature_collection<double>>()
-        && !geoJSON.get<mapbox::geometry::feature_collection<double>>().empty()) {
+        && geoJSON.is<mapbox::feature::feature_collection<double>>()
+        && !geoJSON.get<mapbox::feature::feature_collection<double>>().empty()) {
         mapbox::supercluster::Options clusterOptions;
         clusterOptions.maxZoom = options.clusterMaxZoom;
         clusterOptions.extent = util::EXTENT;
         clusterOptions.radius = ::round(scale * options.clusterRadius);
         data = std::make_unique<SuperclusterData>(
-            geoJSON.get<mapbox::geometry::feature_collection<double>>(), clusterOptions);
+            geoJSON.get<mapbox::feature::feature_collection<double>>(), clusterOptions);
     } else {
         mapbox::geojsonvt::Options vtOptions;
         vtOptions.maxZoom = options.maxzoom;
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.hpp
index a524bab9f..957cf5308 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/style/sources/geojson_source_impl.hpp
@@ -14,7 +14,7 @@ namespace style {
 class GeoJSONData {
 public:
     virtual ~GeoJSONData() = default;
-    virtual mapbox::geometry::feature_collection<int16_t> getTile(const CanonicalTileID&) = 0;
+    virtual mapbox::feature::feature_collection<int16_t> getTile(const CanonicalTileID&) = 0;
 };
 
 class GeoJSONSource::Impl : public Source::Impl {
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/custom_geometry_tile.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/custom_geometry_tile.cpp
index 24f352618..7e99a4568 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/custom_geometry_tile.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/custom_geometry_tile.cpp
@@ -30,7 +30,7 @@ CustomGeometryTile::~CustomGeometryTile() {
 
 void CustomGeometryTile::setTileData(const GeoJSON& geoJSON) {
 
-    auto featureData = mapbox::geometry::feature_collection<int16_t>();
+    auto featureData = mapbox::feature::feature_collection<int16_t>();
     if (geoJSON.is<FeatureCollection>() && !geoJSON.get<FeatureCollection>().empty()) {
         const double scale = util::EXTENT / options.tileSize;
 
@@ -76,7 +76,7 @@ void CustomGeometryTile::querySourceFeatures(
         auto featureCount = layer->featureCount();
         for (std::size_t i = 0; i < featureCount; i++) {
             auto feature = layer->getFeature(i);
-            
+
             // Apply filter, if any
             if (queryOptions.filter && !(*queryOptions.filter)(style::expression::EvaluationContext { static_cast<float>(id.overscaledZ), feature.get() })) {
                 continue;
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.cpp
index 7a83da226..4cf971df8 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.cpp
@@ -8,19 +8,19 @@ namespace mbgl {
 GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
                          std::string sourceID_,
                          const TileParameters& parameters,
-                         mapbox::geometry::feature_collection<int16_t> features)
+                         mapbox::feature::feature_collection<int16_t> features)
     : GeometryTile(overscaledTileID, sourceID_, parameters) {
     updateData(std::move(features));
 }
 
-void GeoJSONTile::updateData(mapbox::geometry::feature_collection<int16_t> features) {
+void GeoJSONTile::updateData(mapbox::feature::feature_collection<int16_t> features) {
     setData(std::make_unique<GeoJSONTileData>(std::move(features)));
 }
-    
+
 void GeoJSONTile::querySourceFeatures(
     std::vector<Feature>& result,
     const SourceQueryOptions& options) {
-    
+
     // Ignore the sourceLayer, there is only one
     if (auto tileData = getData()) {
         if (auto layer = tileData->getLayer({})) {
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.hpp
index 270406267..725dc4850 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile.hpp
@@ -12,10 +12,10 @@ public:
     GeoJSONTile(const OverscaledTileID&,
                 std::string sourceID,
                 const TileParameters&,
-                mapbox::geometry::feature_collection<int16_t>);
+                mapbox::feature::feature_collection<int16_t>);
+
+    void updateData(mapbox::feature::feature_collection<int16_t>);
 
-    void updateData(mapbox::geometry::feature_collection<int16_t>);
-    
     void querySourceFeatures(
         std::vector<Feature>& result,
         const SourceQueryOptions&) override;
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile_data.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile_data.hpp
index 3402c2a00..3605af969 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile_data.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geojson_tile_data.hpp
@@ -7,9 +7,9 @@ namespace mbgl {
 
 class GeoJSONTileFeature : public GeometryTileFeature {
 public:
-    const mapbox::geometry::feature<int16_t>& feature;
+    const mapbox::feature::feature<int16_t>& feature;
 
-    GeoJSONTileFeature(const mapbox::geometry::feature<int16_t>& feature_)
+    GeoJSONTileFeature(const mapbox::feature::feature<int16_t>& feature_)
         : feature(feature_) {
     }
 
@@ -21,7 +21,7 @@ public:
         return feature.properties;
     }
 
-    optional<FeatureIdentifier> getID() const override {
+    FeatureIdentifier getID() const override {
         return feature.id;
     }
 
@@ -47,7 +47,7 @@ public:
 
 class GeoJSONTileLayer : public GeometryTileLayer {
 public:
-    GeoJSONTileLayer(std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features_)
+    GeoJSONTileLayer(std::shared_ptr<const mapbox::feature::feature_collection<int16_t>> features_)
         : features(std::move(features_)) {
     }
 
@@ -64,17 +64,17 @@ public:
     }
 
 private:
-    std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features;
+    std::shared_ptr<const mapbox::feature::feature_collection<int16_t>> features;
 };
 
 class GeoJSONTileData : public GeometryTileData {
 public:
-    GeoJSONTileData(mapbox::geometry::feature_collection<int16_t> features_)
-        : features(std::make_shared<mapbox::geometry::feature_collection<int16_t>>(
+    GeoJSONTileData(mapbox::feature::feature_collection<int16_t> features_)
+        : features(std::make_shared<mapbox::feature::feature_collection<int16_t>>(
               std::move(features_))) {
     }
 
-    GeoJSONTileData(std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features_)
+    GeoJSONTileData(std::shared_ptr<const mapbox::feature::feature_collection<int16_t>> features_)
         : features(std::move(features_)) {
     }
 
@@ -88,7 +88,7 @@ public:
 
 
 private:
-    std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features;
+    std::shared_ptr<const mapbox::feature::feature_collection<int16_t>> features;
 };
 
 } // namespace mbgl
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geometry_tile_data.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geometry_tile_data.hpp
index bd64a1d15..6ce67a532 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geometry_tile_data.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/geometry_tile_data.hpp
@@ -43,7 +43,7 @@ public:
     virtual FeatureType getType() const = 0;
     virtual optional<Value> getValue(const std::string& key) const = 0;
     virtual PropertyMap getProperties() const { return PropertyMap(); }
-    virtual optional<FeatureIdentifier> getID() const { return {}; }
+    virtual FeatureIdentifier getID() const { return NullValue {}; }
     virtual GeometryCollection getGeometries() const = 0;
 };
 
@@ -83,6 +83,9 @@ Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
 GeometryCollection fixupPolygons(const GeometryCollection&);
 
 struct ToGeometryCollection {
+    GeometryCollection operator()(const mapbox::geometry::empty&) const {
+        return GeometryCollection();
+    }
     GeometryCollection operator()(const mapbox::geometry::point<int16_t>& geom) const {
         return { { geom } };
     }
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.cpp
index 2d4a01bda..6363b0d3d 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.cpp
@@ -29,7 +29,7 @@ std::unordered_map<std::string, Value> VectorTileFeature::getProperties() const
     return feature.getProperties();
 }
 
-optional<FeatureIdentifier> VectorTileFeature::getID() const {
+FeatureIdentifier VectorTileFeature::getID() const {
     return feature.getID();
 }
 
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.hpp b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.hpp
index 48beaf9d0..7c95121a3 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.hpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/tile/vector_tile_data.hpp
@@ -16,7 +16,7 @@ public:
     FeatureType getType() const override;
     optional<Value> getValue(const std::string& key) const override;
     std::unordered_map<std::string, Value> getProperties() const override;
-    optional<FeatureIdentifier> getID() const override;
+    FeatureIdentifier getID() const override;
     GeometryCollection getGeometries() const override;
 
 private:
diff --git a/src/3rdparty/mapbox-gl-native/src/mbgl/util/tile_cover_impl.cpp b/src/3rdparty/mapbox-gl-native/src/mbgl/util/tile_cover_impl.cpp
index 799ff2666..f783dfc4b 100644
--- a/src/3rdparty/mapbox-gl-native/src/mbgl/util/tile_cover_impl.cpp
+++ b/src/3rdparty/mapbox-gl-native/src/mbgl/util/tile_cover_impl.cpp
@@ -205,6 +205,10 @@ struct BuildBoundsMap {
             buildTable(ring, et, true);
         }
     }
+    BoundsMap operator()(const EmptyGeometry&) const {
+        return {};
+    }
+
     BoundsMap operator()(const Point<double>&p) const {
         Bound bnd;
         auto point = p;
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/casemap_internal.h b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/casemap_internal.h
index b97f37c6b..1ed873ebc 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/casemap_internal.h
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/casemap_internal.h
@@ -4,6 +4,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <libnu/mph.h>
 #include <libnu/udb.h>
 
 /** Casemap codepoint
@@ -13,7 +14,7 @@
 static inline
 const char* _nu_to_something(uint32_t codepoint,
 	const int16_t *G, size_t G_SIZE,
-	const uint32_t *VALUES_C, const uint16_t *VALUES_I, const uint8_t *COMBINED) {
+	const nu_mph_codepoints_t *VALUES_C, const uint16_t *VALUES_I, const uint8_t *COMBINED) {
 
 	return nu_udb_lookup(codepoint, G, G_SIZE, VALUES_C, VALUES_I, COMBINED);
 }
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/config.h b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/config.h
index 6948815b6..d05573b65 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/config.h
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/config.h
@@ -29,6 +29,9 @@
  *
  * NU_DISABLE_CONTRACTIONS: disables forward-reading during collation,
  * only weights of a single codepoints will be compared (enabled in release build)
+ *
+ * NU_WITH_BMP_ONLY: build collations variant with BMP codepoints only
+ * http://unicode.org/roadmaps/bmp/
  */
 
 /* Enable everything, see below for details on a specific option */
@@ -153,14 +156,12 @@
 /* Requirements for collation functions on 0-terminated strings */
 #ifdef NU_WITH_Z_COLLATION
 # define NU_WITH_Z_STRINGS
-# define NU_WITH_TOUPPER /* nu_toupper() */
 #endif
 
 /* Requirements for collation functions
  * on unterminated strings */
 #ifdef NU_WITH_N_COLLATION
 # define NU_WITH_N_STRINGS
-# define NU_WITH_TOUPPER
 #endif
 
 /* Requirements for casemap functions */
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/defines.h b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/defines.h
index 2678013f9..68f5eb2c7 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/defines.h
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/defines.h
@@ -29,7 +29,7 @@
  *
  * @ingroup defines
  */
-#define NU_UNICODE_VERSION 1000
+#define NU_UNICODE_VERSION 1200
 /** Special limit value to unset limit on string. Used internally by nunicode.
  *
  * @ingroup defines
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/mph.h b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/mph.h
index 53f2043ad..150edeefc 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/mph.h
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/mph.h
@@ -17,8 +17,17 @@ extern "C" {
 
 #ifdef NU_WITH_UDB
 
+typedef uint16_t nu_mph_codepoints_bmp_t;
+typedef uint32_t nu_mph_codepoints_full_t;
+
+#ifdef NU_WITH_BMP_ONLY
+	typedef nu_mph_codepoints_bmp_t nu_mph_codepoints_t;
+#else
+	typedef nu_mph_codepoints_full_t nu_mph_codepoints_t;
+#endif /* NU_BMP_ONLY */
+
 /* those need to be the same values as used in MPH generation */
-#define PRIME        0x01000193
+#define PRIME 0x01000193
 
 /** Calculate G offset from codepoint
  */
@@ -48,10 +57,10 @@ uint32_t nu_mph_hash(const int16_t *G, size_t G_SIZE,
 /** Lookup value in MPH
  */
 static inline
-uint32_t nu_mph_lookup(const uint32_t *V_C, const uint16_t *V_I,
+uint32_t nu_mph_lookup(const nu_mph_codepoints_t *V_C, const uint16_t *V_I,
 	uint32_t codepoint, uint32_t hash) {
 
-	const uint32_t *c = (V_C + hash);
+	const nu_mph_codepoints_t *c = (V_C + hash);
 	const uint16_t *i = (V_I + hash);
 
 	/* due to nature of minimal perfect hash, it will always
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/udb.h b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/udb.h
index 39a785bc6..3e2624f79 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/udb.h
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/udb.h
@@ -35,7 +35,7 @@ extern "C" {
 static inline
 uint32_t nu_udb_lookup_value(uint32_t codepoint,
 	const int16_t *G, size_t G_SIZE,
-	const uint32_t *VALUES_C, const uint16_t *VALUES_I) {
+	const nu_mph_codepoints_t *VALUES_C, const uint16_t *VALUES_I) {
 
 	uint32_t hash = nu_mph_hash(G, G_SIZE, codepoint);
 	uint32_t value = nu_mph_lookup(VALUES_C, VALUES_I, codepoint, hash);
@@ -60,7 +60,7 @@ uint32_t nu_udb_lookup_value(uint32_t codepoint,
 static inline
 const char* nu_udb_lookup(uint32_t codepoint,
 	const int16_t *G, size_t G_SIZE,
-	const uint32_t *VALUES_C, const uint16_t *VALUES_I, const uint8_t *COMBINED) {
+	const nu_mph_codepoints_t *VALUES_C, const uint16_t *VALUES_I, const uint8_t *COMBINED) {
 
 	uint32_t combined_offset = nu_udb_lookup_value(codepoint,
 		G, G_SIZE, VALUES_C, VALUES_I);
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/unaccent.h b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/unaccent.h
index 1486a43f3..a92ac9214 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/unaccent.h
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/include/libnu/unaccent.h
@@ -17,7 +17,7 @@ extern "C" {
 /** Return unaccented value of codepoint. If codepoint is
  * accent (disacritic) itself, returns empty string.
  *
- * @note This is nunicode extenstion.
+ * @note This is nunicode extension.
  *
  * @ingroup transformations
  * @param codepoint unicode codepoint
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/ducet.c b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/ducet.c
index b63453848..0a4ef2020 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/ducet.c
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/ducet.c
@@ -5,10 +5,18 @@
 
 #ifdef NU_WITH_DUCET
 
-#include "gen/_ducet.c"
+#ifndef NU_WITH_BMP_ONLY
+# include "gen/_ducet.c"
+#else
+# include "gen/_ducet_compact.c"
+#endif /* NU_WITH_BMP_ONLY */
 
 #ifndef NU_DISABLE_CONTRACTIONS
-#	include "gen/_ducet_switch.c"
+# ifndef NU_WITH_BMP_ONLY
+#  include "gen/_ducet_switch.c"
+# else
+#  include "gen/_ducet_switch_compact.c"
+# endif /* NU_WITH_BMP_ONLY */
 #else
 	const size_t _NU_DUCET_CONTRACTIONS = 0;
 #endif
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tolower.c b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tolower.c
index 1ce229d37..2a9d3c2b8 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tolower.c
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tolower.c
@@ -5,7 +5,11 @@
 #ifdef NU_WITH_TOLOWER
 
 #include <libnu/casemap_internal.h>
-#include "gen/_tolower.c"
+#ifndef NU_WITH_BMP_ONLY
+# include "gen/_tolower.c"
+#else
+# include "gen/_tolower_compact.c"
+#endif /* NU_WITH_BMP_ONLY */
 
 /* in nu_casemap_read (UTF-8), zero-terminated */
 static const char *__nu_final_sigma = "ς";
@@ -33,8 +37,6 @@ const char* _nu_tolower(const char *encoded, const char *limit, nu_read_iterator
 	 * this is the only language-independent exception described in
 	 * SpecialCasing.txt (Unicode 7.0) */
 
-	assert(nu_casemap_read == nu_utf8_read);
-
 	if (_u == 0x03A3) {
 		if (np >= limit) {
 			*transform = __nu_final_sigma;
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tounaccent.c b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tounaccent.c
index ad5b26982..bf9f99ca4 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tounaccent.c
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/tounaccent.c
@@ -5,7 +5,14 @@
 #ifdef NU_WITH_UNACCENT
 
 #include <libnu/casemap_internal.h>
-#include "gen/_tounaccent.c"
+#ifndef NU_WITH_BMP_ONLY
+# include "gen/_tounaccent.c"
+#else
+# include "gen/_tounaccent_compact.c"
+#endif /* NU_WITH_BMP_ONLY */
+
+/* in nu_casemap_read (UTF-8), zero-terminated */
+static const char *__nu_empty_string = "";
 
 const char* nu_tounaccent(uint32_t codepoint) {
 	typedef struct {
@@ -23,11 +30,10 @@ const char* nu_tounaccent(uint32_t codepoint) {
 
 	/* check if codepoint itself is a diacritic,
 	 * return empty string in that case
-	 * (transform into empty string */
-	assert(nu_casemap_read == nu_utf8_read);
+	 * (transform into empty string) */
 	for (size_t i = 0; i < blocks_count; ++i) {
 		if (codepoint >= blocks[i].block_start && codepoint <= blocks[i].block_end) {
-			return ""; /* return zero-terminated empty string in nu_casemap_read (utf-8) */
+			return __nu_empty_string;
 		}
 	}
 
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/toupper.c b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/toupper.c
index fad3941e6..e0fe44f56 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/toupper.c
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/src/libnu/toupper.c
@@ -3,7 +3,11 @@
 #ifdef NU_WITH_TOUPPER
 
 #include <libnu/casemap_internal.h>
-#include "gen/_toupper.c"
+#ifndef NU_WITH_BMP_ONLY
+# include "gen/_toupper.c"
+#else
+# include "gen/_toupper_compact.c"
+#endif /* NU_WITH_BMP_ONLY */
 
 const char* nu_toupper(uint32_t codepoint) {
 	return _nu_to_something(codepoint, NU_TOUPPER_G, NU_TOUPPER_G_SIZE,
diff --git a/src/3rdparty/mapbox-gl-native/vendor/nunicode/version.txt b/src/3rdparty/mapbox-gl-native/vendor/nunicode/version.txt
index 625934097..096015870 100644
--- a/src/3rdparty/mapbox-gl-native/vendor/nunicode/version.txt
+++ b/src/3rdparty/mapbox-gl-native/vendor/nunicode/version.txt
@@ -1 +1 @@
-1.8
+1.11
