summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/custom_tile_loader.cpp114
-rw-r--r--src/mbgl/style/custom_tile_loader.hpp47
-rw-r--r--src/mbgl/style/sources/custom_geometry_source.cpp45
-rw-r--r--src/mbgl/style/sources/custom_geometry_source_impl.cpp40
-rw-r--r--src/mbgl/style/sources/custom_geometry_source_impl.hpp29
-rw-r--r--src/mbgl/style/types.cpp1
6 files changed, 276 insertions, 0 deletions
diff --git a/src/mbgl/style/custom_tile_loader.cpp b/src/mbgl/style/custom_tile_loader.cpp
new file mode 100644
index 0000000000..2fc94c9d5a
--- /dev/null
+++ b/src/mbgl/style/custom_tile_loader.cpp
@@ -0,0 +1,114 @@
+#include <mbgl/style/custom_tile_loader.hpp>
+
+namespace mbgl {
+namespace style {
+
+CustomTileLoader::CustomTileLoader(const TileFunction& fetchTileFn, const TileFunction& cancelTileFn) {
+ fetchTileFunction = fetchTileFn;
+ cancelTileFunction = cancelTileFn;
+}
+
+void CustomTileLoader::fetchTile(const OverscaledTileID& tileID, ActorRef<SetTileDataFunction> callbackRef) {
+ std::lock_guard<std::mutex> lock(dataCacheMutex);
+ auto cachedTileData = dataCache.find(tileID.canonical);
+ if (cachedTileData != dataCache.end()) {
+ callbackRef.invoke(&SetTileDataFunction::operator(), *(cachedTileData->second));
+ }
+ auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
+ if (tileCallbacks == tileCallbackMap.end()) {
+ auto tuple = std::make_tuple(tileID.overscaledZ, tileID.wrap, callbackRef);
+ tileCallbackMap.insert({ tileID.canonical, std::vector<OverscaledIDFunctionTuple>(1, tuple) });
+ } else {
+ for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
+ if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
+ std::get<2>(*iter) = callbackRef;
+ return;
+ }
+ }
+ tileCallbacks->second.emplace_back(std::make_tuple(tileID.overscaledZ, tileID.wrap, callbackRef));
+ }
+ if (cachedTileData == dataCache.end()) {
+ invokeTileFetch(tileID.canonical);
+ }
+}
+
+void CustomTileLoader::cancelTile(const OverscaledTileID& tileID) {
+ if (tileCallbackMap.find(tileID.canonical) != tileCallbackMap.end()) {
+ invokeTileCancel(tileID.canonical);
+ }
+}
+
+void CustomTileLoader::removeTile(const OverscaledTileID& tileID) {
+ auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
+ if (tileCallbacks == tileCallbackMap.end()) return;
+ for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
+ if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
+ tileCallbacks->second.erase(iter);
+ invokeTileCancel(tileID.canonical);
+ break;
+ }
+ }
+ if (tileCallbacks->second.size() == 0) {
+ std::lock_guard<std::mutex> lock(dataCacheMutex);
+ tileCallbackMap.erase(tileCallbacks);
+ dataCache.erase(tileID.canonical);
+ }
+}
+
+void CustomTileLoader::setTileData(const CanonicalTileID& tileID, const GeoJSON& data) {
+ std::lock_guard<std::mutex> lock(dataCacheMutex);
+
+ auto iter = tileCallbackMap.find(tileID);
+ if (iter == tileCallbackMap.end()) return;
+ dataCache[tileID] = std::make_unique<mapbox::geojson::geojson>(std::move(data));;
+ for (auto tuple : iter->second) {
+ auto actor = std::get<2>(tuple);
+ actor.invoke(&SetTileDataFunction::operator(), data);
+ }
+}
+
+void CustomTileLoader::invalidateTile(const CanonicalTileID& tileID) {
+ auto tileCallbacks = tileCallbackMap.find(tileID);
+ if (tileCallbacks == tileCallbackMap.end()) { return; }
+ for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
+ auto actor = std::get<2>(*iter);
+ actor.invoke(&SetTileDataFunction::operator(), mapbox::geojson::feature_collection());
+ invokeTileCancel(tileID);
+ }
+ tileCallbackMap.erase(tileCallbacks);
+ {
+ std::lock_guard<std::mutex> lock(dataCacheMutex);
+ dataCache.erase(tileID);
+ }
+}
+
+void CustomTileLoader::invalidateRegion(const LatLngBounds& bounds, Range<uint8_t> ) {
+ for (auto idtuple= tileCallbackMap.begin(); idtuple != tileCallbackMap.end(); idtuple++) {
+ const LatLngBounds tileBounds(idtuple->first);
+ if (tileBounds.intersects(bounds) || bounds.contains(tileBounds) || tileBounds.contains(bounds)) {
+ for (auto iter = idtuple->second.begin(); iter != idtuple->second.end(); iter++) {
+ std::lock_guard<std::mutex> lock(dataCacheMutex);
+ auto actor = std::get<2>(*iter);
+ actor.invoke(&SetTileDataFunction::operator(), mapbox::geojson::feature_collection());
+ invokeTileCancel(idtuple->first);
+ dataCache.erase(idtuple->first);
+ }
+ idtuple->second.clear();
+ }
+ }
+}
+
+void CustomTileLoader::invokeTileFetch(const CanonicalTileID& tileID) {
+ if (fetchTileFunction != nullptr) {
+ fetchTileFunction(tileID);
+ }
+}
+
+void CustomTileLoader::invokeTileCancel(const CanonicalTileID& tileID) {
+ if (cancelTileFunction != nullptr) {
+ cancelTileFunction(tileID);
+ }
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/custom_tile_loader.hpp b/src/mbgl/style/custom_tile_loader.hpp
new file mode 100644
index 0000000000..fa3173ffc0
--- /dev/null
+++ b/src/mbgl/style/custom_tile_loader.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/geojson.hpp>
+#include <mbgl/actor/actor_ref.hpp>
+
+#include <map>
+#include <mutex>
+
+namespace mbgl {
+namespace style {
+
+using SetTileDataFunction = std::function<void(const GeoJSON&)>;
+
+class CustomTileLoader : private util::noncopyable {
+public:
+
+ using OverscaledIDFunctionTuple = std::tuple<uint8_t, int16_t, ActorRef<SetTileDataFunction>>;
+
+ CustomTileLoader(const TileFunction& fetchTileFn, const TileFunction& cancelTileFn);
+
+ void fetchTile(const OverscaledTileID& tileID, ActorRef<SetTileDataFunction> callbackRef);
+ void cancelTile(const OverscaledTileID& tileID);
+
+ void removeTile(const OverscaledTileID& tileID);
+ void setTileData(const CanonicalTileID& tileID, const GeoJSON& data);
+
+ void invalidateTile(const CanonicalTileID&);
+ void invalidateRegion(const LatLngBounds&, Range<uint8_t>);
+
+private:
+ void invokeTileFetch(const CanonicalTileID& tileID);
+ void invokeTileCancel(const CanonicalTileID& tileID);
+
+ TileFunction fetchTileFunction;
+ TileFunction cancelTileFunction;
+ std::unordered_map<CanonicalTileID, std::vector<OverscaledIDFunctionTuple>> tileCallbackMap;
+ // Keep around a cache of tile data to serve back for wrapped and over-zooomed tiles
+ std::map<CanonicalTileID, std::unique_ptr<GeoJSON>> dataCache;
+ std::mutex dataCacheMutex;
+
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/custom_geometry_source.cpp b/src/mbgl/style/sources/custom_geometry_source.cpp
new file mode 100644
index 0000000000..657573b1f4
--- /dev/null
+++ b/src/mbgl/style/sources/custom_geometry_source.cpp
@@ -0,0 +1,45 @@
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/style/custom_tile_loader.hpp>
+#include <mbgl/style/sources/custom_geometry_source_impl.hpp>
+#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/tile/tile_id.hpp>
+
+#include <tuple>
+#include <map>
+
+namespace mbgl {
+namespace style {
+
+CustomGeometrySource::CustomGeometrySource(std::string id,
+ const CustomGeometrySource::Options options)
+ : Source(makeMutable<CustomGeometrySource::Impl>(std::move(id), options)),
+ mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
+ loader(std::make_unique<CustomTileLoader>(options.fetchTileFunction, options.cancelTileFunction)) {
+}
+
+CustomGeometrySource::~CustomGeometrySource() = default;
+
+const CustomGeometrySource::Impl& CustomGeometrySource::impl() const {
+ return static_cast<const CustomGeometrySource::Impl&>(*baseImpl);
+}
+
+void CustomGeometrySource::loadDescription(FileSource&) {
+ baseImpl = makeMutable<CustomGeometrySource::Impl>(impl(), ActorRef<CustomTileLoader>(*loader, mailbox));
+ loaded = true;
+}
+
+void CustomGeometrySource::setTileData(const CanonicalTileID& tileID,
+ const GeoJSON& data) {
+ loader->setTileData(tileID, data);
+}
+
+void CustomGeometrySource::invalidateTile(const CanonicalTileID& tileID) {
+ loader->invalidateTile(tileID);
+}
+
+void CustomGeometrySource::invalidateRegion(const LatLngBounds& bounds) {
+ loader->invalidateRegion(bounds, impl().getZoomRange());
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/custom_geometry_source_impl.cpp b/src/mbgl/style/sources/custom_geometry_source_impl.cpp
new file mode 100644
index 0000000000..67d52bdc24
--- /dev/null
+++ b/src/mbgl/style/sources/custom_geometry_source_impl.cpp
@@ -0,0 +1,40 @@
+#include <mbgl/style/sources/custom_geometry_source_impl.hpp>
+#include <mbgl/style/source_observer.hpp>
+
+namespace mbgl {
+namespace style {
+
+CustomGeometrySource::Impl::Impl(std::string id_,
+ const CustomGeometrySource::Options options)
+ : Source::Impl(SourceType::CustomVector, std::move(id_)),
+ tileOptions(options.tileOptions),
+ zoomRange(options.zoomRange),
+ loaderRef({}) {
+}
+
+CustomGeometrySource::Impl::Impl(const Impl& impl, ActorRef<CustomTileLoader> loaderRef_)
+ : Source::Impl(impl),
+ tileOptions(impl.tileOptions),
+ zoomRange(impl.zoomRange),
+ loaderRef(loaderRef_){
+
+}
+
+optional<std::string> CustomGeometrySource::Impl::getAttribution() const {
+ return {};
+}
+
+CustomGeometrySource::TileOptions CustomGeometrySource::Impl::getTileOptions() const {
+ return tileOptions;
+}
+
+Range<uint8_t> CustomGeometrySource::Impl::getZoomRange() const {
+ return zoomRange;
+}
+
+optional<ActorRef<CustomTileLoader>> CustomGeometrySource::Impl::getTileLoader() const {
+ return loaderRef;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/custom_geometry_source_impl.hpp b/src/mbgl/style/sources/custom_geometry_source_impl.hpp
new file mode 100644
index 0000000000..ce7187202d
--- /dev/null
+++ b/src/mbgl/style/sources/custom_geometry_source_impl.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <mbgl/style/source_impl.hpp>
+#include <mbgl/style/sources/custom_geometry_source.hpp>
+#include <mbgl/style/custom_tile_loader.hpp>
+#include <mbgl/actor/actor_ref.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CustomGeometrySource::Impl : public Source::Impl {
+public:
+ Impl(std::string id, CustomGeometrySource::Options options);
+ Impl(const Impl&, ActorRef<CustomTileLoader>);
+
+ optional<std::string> getAttribution() const final;
+
+ CustomGeometrySource::TileOptions getTileOptions() const;
+ Range<uint8_t> getZoomRange() const;
+ optional<ActorRef<CustomTileLoader>> getTileLoader() const;
+
+private:
+ CustomGeometrySource::TileOptions tileOptions;
+ Range<uint8_t> zoomRange;
+ optional<ActorRef<CustomTileLoader>> loaderRef;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
index 0a1781e01b..cd5e597fc0 100644
--- a/src/mbgl/style/types.cpp
+++ b/src/mbgl/style/types.cpp
@@ -12,6 +12,7 @@ MBGL_DEFINE_ENUM(SourceType, {
{ SourceType::Video, "video" },
{ SourceType::Annotations, "annotations" },
{ SourceType::Image, "image" },
+ { SourceType::CustomVector, "customvector" }
});
MBGL_DEFINE_ENUM(VisibilityType, {