Apply just the changes from the MLT branch which aren't really part of that work (#3793)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <mbgl/storage/http_file_source.hpp>
|
||||
#include <mbgl/storage/resource_options.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
@@ -16,23 +17,24 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
|
||||
static void handleError(CURLMcode code) {
|
||||
namespace {
|
||||
void handleError(CURLMcode code) {
|
||||
if (code != CURLM_OK) {
|
||||
throw std::runtime_error(std::string("CURL multi error: ") + curl_multi_strerror(code));
|
||||
}
|
||||
}
|
||||
|
||||
static void handleError(CURLcode code) {
|
||||
void handleError(CURLcode code) {
|
||||
if (code != CURLE_OK) {
|
||||
throw std::runtime_error(std::string("CURL easy error: ") + curl_easy_strerror(code));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -233,10 +235,8 @@ int HTTPFileSource::Impl::startTimeout(CURLM * /* multi */, long timeout_ms, voi
|
||||
assert(userp);
|
||||
auto context = reinterpret_cast<Impl *>(userp);
|
||||
|
||||
if (timeout_ms < 0) {
|
||||
// A timeout of 0 ms means that the timer will invoked in the next loop iteration.
|
||||
timeout_ms = 0;
|
||||
}
|
||||
// A timeout of 0 ms means that the timer will invoked in the next loop iteration.
|
||||
timeout_ms = std::max<long>(timeout_ms, 0);
|
||||
|
||||
context->timeout.stop();
|
||||
context->timeout.start(mbgl::Milliseconds(timeout_ms), Duration::zero(), std::bind(&Impl::onTimeout, context));
|
||||
@@ -245,22 +245,22 @@ int HTTPFileSource::Impl::startTimeout(CURLM * /* multi */, long timeout_ms, voi
|
||||
}
|
||||
|
||||
void HTTPFileSource::Impl::setResourceOptions(ResourceOptions options) {
|
||||
std::lock_guard<std::mutex> lock(resourceOptionsMutex);
|
||||
std::lock_guard lock(resourceOptionsMutex);
|
||||
resourceOptions = options;
|
||||
}
|
||||
|
||||
ResourceOptions HTTPFileSource::Impl::getResourceOptions() {
|
||||
std::lock_guard<std::mutex> lock(resourceOptionsMutex);
|
||||
std::lock_guard lock(resourceOptionsMutex);
|
||||
return resourceOptions.clone();
|
||||
}
|
||||
|
||||
void HTTPFileSource::Impl::setClientOptions(ClientOptions options) {
|
||||
std::lock_guard<std::mutex> lock(clientOptionsMutex);
|
||||
std::lock_guard lock(clientOptionsMutex);
|
||||
clientOptions = options;
|
||||
}
|
||||
|
||||
ClientOptions HTTPFileSource::Impl::getClientOptions() {
|
||||
std::lock_guard<std::mutex> lock(clientOptionsMutex);
|
||||
std::lock_guard lock(clientOptionsMutex);
|
||||
return clientOptions.clone();
|
||||
}
|
||||
|
||||
@@ -338,6 +338,7 @@ size_t HTTPRequest::writeCallback(void *const contents, const size_t size, const
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Compares the beginning of the (non-zero-terminated!) data buffer with the
|
||||
// (zero-terminated!) header string. If the data buffer contains the header
|
||||
// string at the beginning, it returns the length of the header string == begin
|
||||
@@ -354,6 +355,7 @@ size_t headerMatches(const char *const header, const char *const buffer, const s
|
||||
}
|
||||
return i == headerLength ? i : std::string::npos;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
size_t HTTPRequest::headerCallback(char *const buffer, const size_t size, const size_t nmemb, void *userp) {
|
||||
assert(userp);
|
||||
|
||||
@@ -72,11 +72,9 @@ public:
|
||||
|
||||
std::string db_path(const std::string &path) { return path.substr(0, path.find('?')); }
|
||||
|
||||
bool is_compressed(const std::string &v) { return (((uint8_t)v[0]) == 0x1f) && (((uint8_t)v[1]) == 0x8b); }
|
||||
|
||||
// Generate a tilejson resource from .mbtiles file
|
||||
void request_tilejson(const Resource &resource, ActorRef<FileSourceRequest> req) {
|
||||
auto path = url_to_path(resource.url);
|
||||
const auto path = url_to_path(resource.url);
|
||||
|
||||
Response response;
|
||||
|
||||
@@ -88,12 +86,12 @@ public:
|
||||
|
||||
mapbox::sqlite::Statement meta(db, "SELECT * from metadata");
|
||||
for (mapbox::sqlite::Query q(meta); q.run();) {
|
||||
auto name = q.get<std::string>(0);
|
||||
const auto name = q.get<std::string>(0);
|
||||
auto val = q.get<std::string>(1);
|
||||
if (name == "json") {
|
||||
doc.Parse(val.c_str());
|
||||
} else {
|
||||
values[name] = val;
|
||||
values[name] = std::move(val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,25 +102,25 @@ public:
|
||||
values["tilejson"] = "2.0.0";
|
||||
values["scheme"] = "xyz";
|
||||
|
||||
auto format_ptr = values.find("format");
|
||||
std::string format = format_ptr == values.end() ? "png" : format_ptr->second;
|
||||
const auto format_ptr = values.find("format");
|
||||
const std::string format = (format_ptr == values.end()) ? "png" : format_ptr->second;
|
||||
|
||||
if (format != "pbf" && values.count("scale") == 0) {
|
||||
if (format != "pbf" && !values.contains("scale")) {
|
||||
values["scale"] = "1";
|
||||
}
|
||||
|
||||
// We use file location with appended parameter query parameter as URL for actual tile data
|
||||
std::string tile_url = std::string(resource.url + "?file={x}/{y}/{z}." + format);
|
||||
rapidjson::Value arr(kArrayType);
|
||||
rapidjson::Value tile_url_val(tile_url, allocator);
|
||||
rapidjson::Value tile_url_val(std::move(tile_url), allocator);
|
||||
arr.PushBack(tile_url_val, allocator);
|
||||
doc.AddMember("tiles", arr, allocator);
|
||||
|
||||
std::string minz;
|
||||
std::string maxz;
|
||||
|
||||
auto minzoom_ptr = values.find("minzoom");
|
||||
auto maxzoom_ptr = values.find("maxzoom");
|
||||
const auto minzoom_ptr = values.find("minzoom");
|
||||
const auto maxzoom_ptr = values.find("maxzoom");
|
||||
|
||||
if (minzoom_ptr == values.end() || maxzoom_ptr == values.end()) {
|
||||
mapbox::sqlite::Statement zoom_stmt(db, "SELECT MIN(zoom_level),MAX(zoom_level) from tiles");
|
||||
@@ -139,42 +137,43 @@ public:
|
||||
maxz = maxzoom_ptr->second;
|
||||
}
|
||||
|
||||
auto minZoom = std::stoi(minz);
|
||||
auto maxZoom = std::stoi(maxz);
|
||||
const auto minZoom = minz.empty() ? 0 : std::stoi(minz);
|
||||
const auto maxZoom = maxz.empty() ? 0 : std::stoi(maxz);
|
||||
|
||||
for (auto const &entry : values) {
|
||||
if (entry.first == "scale") {
|
||||
doc.AddMember("scale", std::stod(entry.second), allocator);
|
||||
} else if (entry.first == "minzoom" || entry.first == "maxzoom") {
|
||||
auto name = rapidjson::Value(entry.first, allocator);
|
||||
doc.AddMember(name, std::stoi(entry.second), allocator);
|
||||
Document::ValueType value{entry.second.empty() ? 0 : std::stoi(entry.second)};
|
||||
doc.AddMember(std::move(name), std::move(value), allocator);
|
||||
} else if (entry.first == "bounds") {
|
||||
std::vector<double> x = split(entry.second, ',');
|
||||
if (x.size() != 4) {
|
||||
const std::vector<double> bounds_values = split(entry.second, ',');
|
||||
if (bounds_values.size() != 4) {
|
||||
response.error = std::make_unique<Response::Error>(Response::Error::Reason::Other);
|
||||
req.invoke(&FileSourceRequest::setResponse, response);
|
||||
return;
|
||||
}
|
||||
double cLon = (x[0] + x[2]) / 2;
|
||||
double cLat = (x[1] + x[3]) / 2;
|
||||
int cZoom = (minZoom + maxZoom) / 2;
|
||||
rapidjson::Value bounds_arr(kArrayType);
|
||||
for (auto vv : x) {
|
||||
bounds_arr.PushBack(vv, allocator);
|
||||
}
|
||||
const double cLon = (bounds_values[0] + bounds_values[2]) / 2;
|
||||
const double cLat = (bounds_values[1] + bounds_values[3]) / 2;
|
||||
const int cZoom = (minZoom + maxZoom) / 2;
|
||||
|
||||
if (format != "pbf") {
|
||||
doc.AddMember("bounds", bounds_arr, allocator);
|
||||
rapidjson::Value bounds_arr(kArrayType);
|
||||
for (auto vv : bounds_values) {
|
||||
bounds_arr.PushBack(vv, allocator);
|
||||
}
|
||||
doc.AddMember("bounds", std::move(bounds_arr), allocator);
|
||||
}
|
||||
|
||||
rapidjson::Value center_arr(kArrayType);
|
||||
center_arr.PushBack(cLon, allocator);
|
||||
center_arr.PushBack(cLat, allocator);
|
||||
center_arr.PushBack(cZoom, allocator);
|
||||
doc.AddMember("center", center_arr, allocator);
|
||||
doc.AddMember("center", std::move(center_arr), allocator);
|
||||
} else {
|
||||
rapidjson::Value name = rapidjson::Value(entry.first, allocator);
|
||||
doc.AddMember(name, rapidjson::Value(entry.second, allocator), allocator);
|
||||
doc.AddMember(std::move(name), rapidjson::Value(entry.second, allocator), allocator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +209,7 @@ public:
|
||||
response.expires = Timestamp::max();
|
||||
response.etag = resource.url;
|
||||
|
||||
if (is_compressed(*response.data)) {
|
||||
if (util::is_compressed(*response.data)) {
|
||||
response.data = std::make_shared<std::string>(util::decompress(*response.data));
|
||||
}
|
||||
}
|
||||
@@ -250,7 +249,7 @@ private:
|
||||
|
||||
void close_all() { db_cache.clear(); }
|
||||
|
||||
// Multiple databases open simultaneoulsy, to effectively support multiple .mbtiles maps
|
||||
// Multiple databases open simultaneously, to effectively support multiple .mbtiles maps
|
||||
mapbox::sqlite::Database &get_db(const std::string &path) {
|
||||
auto ptr = db_cache.find(path);
|
||||
if (ptr != db_cache.end()) {
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
req,
|
||||
tileID,
|
||||
header.root_dir_offset,
|
||||
static_cast<uint32_t>(header.root_dir_bytes),
|
||||
static_cast<std::uint32_t>(header.root_dir_bytes),
|
||||
0,
|
||||
[=, this](std::pair<uint64_t, uint32_t> tileAddress, std::unique_ptr<Response::Error> tileError) {
|
||||
if (tileError) {
|
||||
|
||||
@@ -31,6 +31,29 @@ namespace util {
|
||||
// cause a link error.
|
||||
#undef compress
|
||||
|
||||
bool is_compressed(const std::string &v) {
|
||||
if (v.size() > 2) {
|
||||
const auto byte0 = static_cast<uint8_t>(v[0]);
|
||||
const auto byte1 = static_cast<uint8_t>(v[1]);
|
||||
if (byte0 == 0x1f && byte1 == 0x8b) {
|
||||
// gzip (rfc1952)
|
||||
return true;
|
||||
} else if (byte0 == 0x78) {
|
||||
// zlib (rfc1950)
|
||||
switch (byte1) {
|
||||
case 0x01: // 78 01 - No Compression/low
|
||||
case 0x5E: // 78 5E - Fast Compression
|
||||
case 0x9C: // 78 9C - Default Compression
|
||||
case 0xDA: // 78 DA - Best Compression
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string compress(const std::string &raw, int windowBits) {
|
||||
z_stream deflate_stream;
|
||||
memset(&deflate_stream, 0, sizeof(deflate_stream));
|
||||
@@ -79,14 +102,13 @@ std::string decompress(const std::string &raw, int windowBits) {
|
||||
inflate_stream.avail_in = uInt(raw.size());
|
||||
|
||||
std::string result;
|
||||
char out[15384];
|
||||
char out[16384];
|
||||
|
||||
int code;
|
||||
do {
|
||||
inflate_stream.next_out = reinterpret_cast<Bytef *>(out);
|
||||
inflate_stream.avail_out = sizeof(out);
|
||||
code = inflate(&inflate_stream, 0);
|
||||
// result.append(out, sizeof(out) - inflate_stream.avail_out);
|
||||
if (result.size() < inflate_stream.total_out) {
|
||||
result.append(out, inflate_stream.total_out - result.size());
|
||||
}
|
||||
|
||||
@@ -2498,7 +2498,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
|
||||
break;
|
||||
|
||||
case MLNTileOperationCancelled:
|
||||
NSLog(@"Pending work on tile %@", tileStr);
|
||||
NSLog(@"Pending work cancelled on tile %@", tileStr);
|
||||
break;
|
||||
|
||||
case MLNTileOperationNullOp:
|
||||
|
||||
3
platform/ios/ios.toolchain.cmake
Normal file
3
platform/ios/ios.toolchain.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
set(CMAKE_SYSTEM_NAME iOS)
|
||||
set(CMAKE_SYSTEM_VERSION 15.0)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm64)
|
||||
@@ -166,7 +166,7 @@ void MLNMapViewImpl::onGlyphsRequested(const mbgl::FontStack& fontStack, const m
|
||||
void MLNMapViewImpl::onTileAction(mbgl::TileOperation operation, const mbgl::OverscaledTileID& tile, const std::string& sourceID) {
|
||||
[mapView tileDidTriggerAction:MLNTileOperation(static_cast<int>(operation))
|
||||
x:tile.canonical.x
|
||||
y:tile.canonical.x
|
||||
y:tile.canonical.y
|
||||
z:tile.canonical.z
|
||||
wrap:tile.wrap
|
||||
overscaledZ:tile.overscaledZ
|
||||
|
||||
Reference in New Issue
Block a user