1 #include <mbgl/style/custom_tile_loader.hpp>
2 #include <mbgl/tile/custom_geometry_tile.hpp>
3 #include <mbgl/util/tile_range.hpp>
4 
5 namespace mbgl {
6 namespace style {
7 
CustomTileLoader(const TileFunction & fetchTileFn,const TileFunction & cancelTileFn)8 CustomTileLoader::CustomTileLoader(const TileFunction& fetchTileFn, const TileFunction& cancelTileFn) {
9     fetchTileFunction = fetchTileFn;
10     cancelTileFunction = cancelTileFn;
11 }
12 
fetchTile(const OverscaledTileID & tileID,ActorRef<CustomGeometryTile> tileRef)13 void CustomTileLoader::fetchTile(const OverscaledTileID& tileID, ActorRef<CustomGeometryTile> tileRef) {
14     auto cachedTileData = dataCache.find(tileID.canonical);
15     if (cachedTileData != dataCache.end()) {
16         tileRef.invoke(&CustomGeometryTile::setTileData, *(cachedTileData->second));
17     }
18     auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
19     if (tileCallbacks == tileCallbackMap.end()) {
20         auto tuple = std::make_tuple(tileID.overscaledZ, tileID.wrap, tileRef);
21         tileCallbackMap.insert({ tileID.canonical, std::vector<OverscaledIDFunctionTuple>(1, tuple) });
22     } else {
23         for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
24             if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
25                 std::get<2>(*iter) = tileRef;
26                 return;
27             }
28         }
29         tileCallbacks->second.emplace_back(std::make_tuple(tileID.overscaledZ, tileID.wrap, tileRef));
30     }
31     if (cachedTileData == dataCache.end()) {
32         invokeTileFetch(tileID.canonical);
33     }
34 }
35 
cancelTile(const OverscaledTileID & tileID)36 void CustomTileLoader::cancelTile(const OverscaledTileID& tileID) {
37     if (tileCallbackMap.find(tileID.canonical) != tileCallbackMap.end()) {
38         invokeTileCancel(tileID.canonical);
39     }
40 }
41 
removeTile(const OverscaledTileID & tileID)42 void CustomTileLoader::removeTile(const OverscaledTileID& tileID) {
43     auto tileCallbacks = tileCallbackMap.find(tileID.canonical);
44     if (tileCallbacks == tileCallbackMap.end()) return;
45     for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
46         if (std::get<0>(*iter) == tileID.overscaledZ && std::get<1>(*iter) == tileID.wrap ) {
47             tileCallbacks->second.erase(iter);
48             invokeTileCancel(tileID.canonical);
49             break;
50         }
51     }
52     if (tileCallbacks->second.size() == 0) {
53         tileCallbackMap.erase(tileCallbacks);
54         dataCache.erase(tileID.canonical);
55     }
56 }
57 
setTileData(const CanonicalTileID & tileID,const GeoJSON & data)58 void CustomTileLoader::setTileData(const CanonicalTileID& tileID, const GeoJSON& data) {
59 
60     auto iter = tileCallbackMap.find(tileID);
61     if (iter == tileCallbackMap.end()) return;
62     auto dataPtr = std::make_unique<mapbox::geojson::geojson>(std::move(data));
63     for (auto tuple : iter->second) {
64         auto actor = std::get<2>(tuple);
65         actor.invoke(&CustomGeometryTile::setTileData, *dataPtr);
66     }
67     dataCache[tileID] = std::move(dataPtr);
68 }
69 
invalidateTile(const CanonicalTileID & tileID)70 void CustomTileLoader::invalidateTile(const CanonicalTileID& tileID) {
71     auto tileCallbacks = tileCallbackMap.find(tileID);
72     if (tileCallbacks == tileCallbackMap.end()) { return; }
73     for (auto iter = tileCallbacks->second.begin(); iter != tileCallbacks->second.end(); iter++) {
74         auto actor = std::get<2>(*iter);
75         actor.invoke(&CustomGeometryTile::invalidateTileData);
76         invokeTileCancel(tileID);
77     }
78     tileCallbackMap.erase(tileCallbacks);
79     dataCache.erase(tileID);
80 }
81 
invalidateRegion(const LatLngBounds & bounds,Range<uint8_t>)82 void CustomTileLoader::invalidateRegion(const LatLngBounds& bounds, Range<uint8_t> ) {
83     std::map<uint8_t, util::TileRange> tileRanges;
84 
85     for (auto idtuple= tileCallbackMap.begin(); idtuple != tileCallbackMap.end(); idtuple++) {
86         auto zoom = idtuple->first.z;
87         auto tileRange = tileRanges.find(zoom);
88         if(tileRange == tileRanges.end()) {
89             tileRange = tileRanges.emplace(std::make_pair(zoom, util::TileRange::fromLatLngBounds(bounds, zoom))).first;
90         }
91         if (tileRange->second.contains(idtuple->first)) {
92             for (auto iter = idtuple->second.begin(); iter != idtuple->second.end(); iter++) {
93                 auto actor = std::get<2>(*iter);
94                 actor.invoke(&CustomGeometryTile::invalidateTileData);
95                 invokeTileCancel(idtuple->first);
96                 dataCache.erase(idtuple->first);
97             }
98             idtuple->second.clear();
99         }
100     }
101 }
102 
invokeTileFetch(const CanonicalTileID & tileID)103 void CustomTileLoader::invokeTileFetch(const CanonicalTileID& tileID) {
104     if (fetchTileFunction != nullptr) {
105         fetchTileFunction(tileID);
106     }
107 }
108 
invokeTileCancel(const CanonicalTileID & tileID)109 void CustomTileLoader::invokeTileCancel(const CanonicalTileID& tileID) {
110     if (cancelTileFunction != nullptr) {
111         cancelTileFunction(tileID);
112     }
113 }
114 
115 } // namespace style
116 } // namespace mbgl
117