Apply just the changes from the MLT branch which aren't really part of that work (#3793)
This commit is contained in:
@@ -116,7 +116,8 @@ Checks: [
|
||||
-readability-avoid-nested-conditional-operator,
|
||||
-readability-math-missing-parentheses,
|
||||
-readability-enum-initial-value,
|
||||
-boost-use-ranges
|
||||
-boost-use-ranges,
|
||||
-portability-template-virtual-member-function,
|
||||
]
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '.*'
|
||||
|
||||
7
.github/workflows/node-ci.yml
vendored
7
.github/workflows/node-ci.yml
vendored
@@ -94,11 +94,14 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- if: runner.os == 'Windows'
|
||||
run: git config --global core.longpaths true
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Get OS Architecture
|
||||
if: runner.os == 'MacOS' || runner.os == 'Linux'
|
||||
|
||||
7
.github/workflows/qt-ci.yml
vendored
7
.github/workflows/qt-ci.yml
vendored
@@ -98,12 +98,15 @@ jobs:
|
||||
QT_VERSION: ${{ matrix.qt_version }}
|
||||
|
||||
steps:
|
||||
- if: runner.os == 'Windows'
|
||||
run: git config --global core.longpaths true
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
|
||||
- name: Install test dependencies
|
||||
if: runner.os == 'Linux'
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
"generator": "Xcode",
|
||||
"description": "Create Xcode project for iOS",
|
||||
"binaryDir": "${sourceDir}/build-ios",
|
||||
"toolchainFile": "${sourceDir}/platform/ios/ios.toolchain.cmake",
|
||||
"cacheVariables": {
|
||||
"CMAKE_SYSTEM_NAME": "iOS",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
|
||||
"CMAKE_OSX_DEPLOYMENT_TARGET": "14.0",
|
||||
"MLN_WITH_METAL": "ON",
|
||||
"MLN_WITH_OPENGL": "OFF"
|
||||
}
|
||||
@@ -27,6 +29,7 @@
|
||||
"cacheVariables": {
|
||||
"CMAKE_SYSTEM_NAME": "Darwin",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
|
||||
"CMAKE_OSX_DEPLOYMENT_TARGET": "14.3",
|
||||
"MLN_WITH_METAL": "ON",
|
||||
"MLN_WITH_OPENGL": "OFF",
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
@@ -31,7 +31,7 @@ private:
|
||||
|
||||
// unique id used for debugging and profiling purposes
|
||||
// localID should not be used as unique id because a const buffer pool is managed using IBufferAllocator
|
||||
// Currently unique IDs for constant buffers are only used when Tracy profiling is enabled
|
||||
// Currently unique IDs for constant buffers are only used when Tracy profiling is enabled
|
||||
#ifdef MLN_TRACY_ENABLE
|
||||
int64_t uniqueDebugId = -1;
|
||||
#endif
|
||||
|
||||
@@ -21,8 +21,8 @@ public:
|
||||
using Object = std::unordered_map<std::string, expression::Value>;
|
||||
if (context.formattedSection && context.formattedSection->is<Object>()) {
|
||||
const auto& section = context.formattedSection->get<Object>();
|
||||
if (section.find(propertyName) != section.end()) {
|
||||
return section.at(propertyName);
|
||||
if (auto hit = section.find(propertyName); hit != section.end()) {
|
||||
return hit->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace mbgl {
|
||||
template <typename Enum>
|
||||
constexpr Enum operator|(Enum a, Enum b) {
|
||||
static_assert(std::is_enum_v<Enum>, "Enum must be an enum type");
|
||||
// NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
|
||||
return Enum(mbgl::underlying_type(a) | mbgl::underlying_type(b));
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ enum CompressionFormat {
|
||||
DETECT = 15 + 32
|
||||
};
|
||||
|
||||
bool is_compressed(const std::string&);
|
||||
std::string compress(const std::string& raw, int windowBits = CompressionFormat::ZLIB);
|
||||
std::string decompress(const std::string& raw, int windowBits = CompressionFormat::DETECT);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/work_task.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,7 +26,7 @@ void Scheduler::SetCurrent(Scheduler* scheduler) {
|
||||
|
||||
Scheduler* Scheduler::GetCurrent(bool init) {
|
||||
if (!localScheduler && init) {
|
||||
thread_local util::RunLoop runLoop;
|
||||
static thread_local util::RunLoop runLoop;
|
||||
SetCurrent(&runLoop);
|
||||
}
|
||||
return localScheduler;
|
||||
|
||||
@@ -135,10 +135,10 @@ void AnnotationManager::update(const AnnotationID& id, const FillAnnotation& ann
|
||||
|
||||
void AnnotationManager::remove(const AnnotationID& id) {
|
||||
CHECK_ANNOTATIONS_ENABLED_AND_RETURN_NOARG();
|
||||
if (symbolAnnotations.find(id) != symbolAnnotations.end()) {
|
||||
if (symbolAnnotations.contains(id)) {
|
||||
symbolTree.remove(symbolAnnotations.at(id));
|
||||
symbolAnnotations.erase(id);
|
||||
} else if (shapeAnnotations.find(id) != shapeAnnotations.end()) {
|
||||
} else if (shapeAnnotations.contains(id)) {
|
||||
auto it = shapeAnnotations.find(id);
|
||||
(void)*style.get().impl->removeLayer(it->second->layerID);
|
||||
shapeAnnotations.erase(it);
|
||||
|
||||
@@ -154,7 +154,7 @@ struct glyph {
|
||||
|
||||
// Font data From Hershey Simplex Font
|
||||
// http://paulbourke.net/dataformats/hershey/
|
||||
|
||||
// NOLINTBEGIN(modernize-use-designated-initializers)
|
||||
const glyph simplex[] = {
|
||||
/* 32 */ {16, 0, nullptr},
|
||||
/* 33 ! */
|
||||
@@ -346,3 +346,4 @@ const glyph simplex[] = {
|
||||
/* 126 ~ */
|
||||
{24, sizeof(simplex_94), simplex_94},
|
||||
};
|
||||
// NOLINTEND(modernize-use-designated-initializers)
|
||||
|
||||
@@ -210,8 +210,9 @@ void DashPatternTexture::upload(gfx::UploadPass& uploadPass) {
|
||||
if (std::holds_alternative<AlphaImage>(texture)) {
|
||||
auto tempTexture = uploadPass.getContext().createTexture2D();
|
||||
tempTexture->upload(std::get<AlphaImage>(texture));
|
||||
tempTexture->setSamplerConfiguration(
|
||||
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Repeat, gfx::TextureWrapType::Clamp});
|
||||
tempTexture->setSamplerConfiguration({.filter = gfx::TextureFilterType::Linear,
|
||||
.wrapU = gfx::TextureWrapType::Repeat,
|
||||
.wrapV = gfx::TextureWrapType::Clamp});
|
||||
texture = std::move(tempTexture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@ UniqueGPUExpression GPUExpression::create(const Expression& expression, const Zo
|
||||
}
|
||||
|
||||
float GPUExpression::evaluateFloat(const float zoom) const {
|
||||
const auto index = std::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom));
|
||||
const auto index = static_cast<std::uint16_t>(
|
||||
std::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom)));
|
||||
if (index == 0) {
|
||||
return stops.floats[0];
|
||||
} else if (index == stopCount) {
|
||||
@@ -153,7 +154,8 @@ Color GPUExpression::getColor(std::size_t index) const {
|
||||
}
|
||||
|
||||
Color GPUExpression::evaluateColor(const float zoom) const {
|
||||
const auto index = std::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom));
|
||||
const auto index = static_cast<std::uint16_t>(
|
||||
std::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom)));
|
||||
if (index == 0) {
|
||||
return getColor(0);
|
||||
} else if (index == stopCount) {
|
||||
|
||||
@@ -93,14 +93,14 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
|
||||
const std::size_t first = [&coordinates, &len] {
|
||||
std::size_t i = 0;
|
||||
// If the line has duplicate vertices at the start, adjust index to remove them.
|
||||
while (i < len - 1 && coordinates[i] == coordinates[i + 1]) {
|
||||
while (i + 1 < len && coordinates[i] == coordinates[i + 1]) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}();
|
||||
|
||||
// Ignore invalid geometry.
|
||||
if (len < (options.type == FeatureType::Polygon ? 3 : 2)) {
|
||||
if (len < ((options.type == FeatureType::Polygon) ? 3u : 2u)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <mbgl/style/layers/symbol_layer_impl.hpp>
|
||||
#include <mbgl/util/monotonic_timer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
@@ -26,7 +25,7 @@ bool RenderingStats::isZero() const {
|
||||
memIndexBuffers,
|
||||
memVertexBuffers,
|
||||
memUniformBuffers};
|
||||
return std::all_of(expectedZeros.begin(), expectedZeros.end(), [](auto x) { return x == 0; });
|
||||
return std::ranges::all_of(expectedZeros, [](auto x) { return x == 0; });
|
||||
}
|
||||
|
||||
RenderingStats& RenderingStats::operator+=(const RenderingStats& r) {
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace gfx {
|
||||
|
||||
bool ShaderGroup::isShader(const std::string& shaderName) const noexcept {
|
||||
std::shared_lock<std::shared_mutex> readerLock(programLock);
|
||||
return programs.find(shaderName) != programs.end();
|
||||
return programs.contains(shaderName);
|
||||
}
|
||||
|
||||
const std::shared_ptr<gfx::Shader> ShaderGroup::getShader(const std::string& shaderName) const noexcept {
|
||||
@@ -25,7 +25,7 @@ bool ShaderGroup::replaceShader(std::shared_ptr<gfx::Shader>&& shader) noexcept
|
||||
|
||||
bool ShaderGroup::replaceShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept {
|
||||
std::unique_lock<std::shared_mutex> writerLock(programLock);
|
||||
if (programs.find(shaderName) == programs.end()) {
|
||||
if (!programs.contains(shaderName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ bool ShaderGroup::registerShader(std::shared_ptr<gfx::Shader>&& shader) noexcept
|
||||
|
||||
bool ShaderGroup::registerShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept {
|
||||
std::unique_lock<std::shared_mutex> writerLock(programLock);
|
||||
if (programs.find(shaderName) != programs.end()) {
|
||||
if (programs.contains(shaderName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ShaderGroup& ShaderRegistry::getLegacyGroup() noexcept {
|
||||
|
||||
bool ShaderRegistry::isShaderGroup(const std::string& shaderGroupName) const noexcept {
|
||||
std::shared_lock<std::shared_mutex> readerLock(shaderGroupLock);
|
||||
return shaderGroups.find(shaderGroupName) != shaderGroups.end();
|
||||
return shaderGroups.contains(shaderGroupName);
|
||||
}
|
||||
|
||||
const ShaderGroupPtr ShaderRegistry::getShaderGroup(const std::string& shaderGroupName) const noexcept {
|
||||
@@ -28,7 +28,7 @@ const ShaderGroupPtr ShaderRegistry::getShaderGroup(const std::string& shaderGro
|
||||
|
||||
bool ShaderRegistry::replaceShader(ShaderGroupPtr&& shader, const std::string& shaderGroupName) noexcept {
|
||||
std::unique_lock<std::shared_mutex> writerLock(shaderGroupLock);
|
||||
if (shaderGroups.find(shaderGroupName) == shaderGroups.end()) {
|
||||
if (!shaderGroups.contains(shaderGroupName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ bool ShaderRegistry::replaceShader(ShaderGroupPtr&& shader, const std::string& s
|
||||
|
||||
bool ShaderRegistry::registerShaderGroup(ShaderGroupPtr&& shader, const std::string& shaderGroupName) noexcept {
|
||||
std::unique_lock<std::shared_mutex> writerLock(shaderGroupLock);
|
||||
if (shaderGroups.find(shaderGroupName) != shaderGroups.end()) {
|
||||
if (shaderGroups.contains(shaderGroupName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
|
||||
const auto& sortKeyProperty = layout.template get<style::CircleSortKey>();
|
||||
float sortKey = sortKeyProperty.evaluate(*feature, zoom, style::CircleSortKey::defaultValue());
|
||||
CircleFeature circleFeature{i, std::move(feature), sortKey};
|
||||
CircleFeature circleFeature{.i = i, .feature = std::move(feature), .sortKey = sortKey};
|
||||
const auto sortPosition = std::lower_bound(features.cbegin(), features.cend(), circleFeature);
|
||||
features.insert(sortPosition, std::move(circleFeature));
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace util {
|
||||
|
||||
// Map of key -> index into features
|
||||
using Index = std::unordered_map<size_t, size_t>;
|
||||
|
||||
namespace {
|
||||
size_t mergeFromRight(std::vector<SymbolFeature>& features,
|
||||
Index& rightIndex,
|
||||
Index::iterator left,
|
||||
@@ -40,7 +40,7 @@ size_t mergeFromLeft(std::vector<SymbolFeature>& features,
|
||||
size_t getKey(const std::u16string& text, const GeometryCoordinate& coord) {
|
||||
return util::hash(text, coord.x, coord.y);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void mergeLines(std::vector<SymbolFeature>& features) {
|
||||
Index leftIndex;
|
||||
Index rightIndex;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <mbgl/style/layer_properties.hpp>
|
||||
#include <mbgl/util/containers.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class PatternDependency {
|
||||
@@ -54,8 +56,8 @@ struct PatternFeatureInserter<void> {
|
||||
template <typename PropertiesType>
|
||||
static void insert(std::vector<PatternFeature>& features,
|
||||
std::size_t index,
|
||||
std::unique_ptr<GeometryTileFeature> feature,
|
||||
PatternLayerMap patternDependencyMap,
|
||||
std::unique_ptr<GeometryTileFeature>&& feature,
|
||||
PatternLayerMap&& patternDependencyMap,
|
||||
float /*zoom*/,
|
||||
const PropertiesType&,
|
||||
const CanonicalTileID&) {
|
||||
@@ -68,8 +70,8 @@ struct PatternFeatureInserter {
|
||||
template <typename PropertiesType>
|
||||
static void insert(std::vector<PatternFeature>& features,
|
||||
std::size_t index,
|
||||
std::unique_ptr<GeometryTileFeature> feature,
|
||||
PatternLayerMap patternDependencyMap,
|
||||
std::unique_ptr<GeometryTileFeature>&& feature,
|
||||
PatternLayerMap&& patternDependencyMap,
|
||||
float zoom,
|
||||
const PropertiesType& properties,
|
||||
const CanonicalTileID& canonical) {
|
||||
@@ -91,7 +93,7 @@ class PatternLayout : public Layout {
|
||||
public:
|
||||
PatternLayout(const BucketParameters& parameters,
|
||||
const std::vector<Immutable<style::LayerProperties>>& group,
|
||||
std::unique_ptr<GeometryTileLayer> sourceLayer_,
|
||||
std::unique_ptr<GeometryTileLayer>&& sourceLayer_,
|
||||
const LayoutParameters& layoutParameters)
|
||||
: sourceLayer(std::move(sourceLayer_)),
|
||||
zoom(parameters.tileID.overscaledZ),
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <mbgl/text/tagged_string.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
namespace {
|
||||
template <class Property>
|
||||
static bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) {
|
||||
bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) {
|
||||
return layout.get<Property>().match([](const typename Property::Type& t) { return !t.empty(); },
|
||||
[](const auto&) { return true; });
|
||||
}
|
||||
|
||||
namespace {
|
||||
expression::Value sectionOptionsToValue(const SectionOptions& options) {
|
||||
std::unordered_map<std::string, expression::Value> result;
|
||||
// TODO: Data driven properties that can be overridden on per section basis.
|
||||
|
||||
@@ -689,7 +689,7 @@ ScreenCoordinate TransformState::latLngToScreenCoordinate(const LatLng& latLng,
|
||||
|
||||
TileCoordinate TransformState::screenCoordinateToTileCoordinate(const ScreenCoordinate& point, uint8_t atZoom) const {
|
||||
if (size.isEmpty()) {
|
||||
return {{}, 0};
|
||||
return {.p = {}, .z = 0};
|
||||
}
|
||||
|
||||
float targetZ = 0;
|
||||
@@ -718,7 +718,7 @@ TileCoordinate TransformState::screenCoordinateToTileCoordinate(const ScreenCoor
|
||||
double t = z0 == z1 ? 0 : (targetZ - z0) / (z1 - z0);
|
||||
|
||||
Point<double> p = util::interpolate(p0, p1, t) / scale * static_cast<double>(1 << atZoom);
|
||||
return {{p.x, p.y}, static_cast<double>(atZoom)};
|
||||
return {.p = {p.x, p.y}, .z = static_cast<double>(atZoom)};
|
||||
}
|
||||
|
||||
LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const {
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
const ImagePositions&,
|
||||
const PatternLayerMap&,
|
||||
std::size_t,
|
||||
const CanonicalTileID&) {};
|
||||
const CanonicalTileID&) {}
|
||||
|
||||
virtual void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) {}
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ DebugBucket::DebugBucket(const OverscaledTileID& id,
|
||||
const bool complete_,
|
||||
std::optional<Timestamp> modified_,
|
||||
std::optional<Timestamp> expires_,
|
||||
MapDebugOptions debugMode_)
|
||||
MapDebugOptions debugMode_,
|
||||
std::string sourceName_)
|
||||
: renderable(renderable_),
|
||||
complete(complete_),
|
||||
modified(std::move(modified_)),
|
||||
expires(std::move(expires_)),
|
||||
debugMode(debugMode_) {
|
||||
debugMode(debugMode_),
|
||||
sourceName(std::move(sourceName_)) {
|
||||
auto addText = [&](const std::string& text, double left, double baseline, double scale) {
|
||||
for (uint8_t c : text) {
|
||||
if (c < 32 || c >= 127) continue;
|
||||
@@ -53,7 +55,8 @@ DebugBucket::DebugBucket(const OverscaledTileID& id,
|
||||
const std::string text = util::toString(id) + " - " +
|
||||
(complete ? "complete"
|
||||
: renderable ? "renderable"
|
||||
: "pending");
|
||||
: "pending") +
|
||||
" " + sourceName;
|
||||
addText(text, 50, baseline, 5);
|
||||
baseline += 200;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@ public:
|
||||
bool complete,
|
||||
std::optional<Timestamp> modified,
|
||||
std::optional<Timestamp> expires,
|
||||
MapDebugOptions);
|
||||
MapDebugOptions,
|
||||
std::string sourceName);
|
||||
|
||||
void upload(gfx::UploadPass&);
|
||||
|
||||
@@ -31,6 +32,7 @@ public:
|
||||
const std::optional<Timestamp> modified;
|
||||
const std::optional<Timestamp> expires;
|
||||
const MapDebugOptions debugMode;
|
||||
const std::string sourceName;
|
||||
|
||||
gfx::VertexVector<FillLayoutVertex> vertices;
|
||||
gfx::IndexVector<gfx::Lines> indices;
|
||||
|
||||
@@ -428,12 +428,13 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
|
||||
}
|
||||
|
||||
// Prepare. Update all matrices and generate data that we should upload to the GPU.
|
||||
for (const auto& entry : renderSources) {
|
||||
for (const auto& [name, renderSource] : renderSources) {
|
||||
MLN_TRACE_ZONE(prepare source);
|
||||
if (entry.second->isEnabled()) {
|
||||
entry.second->prepare({.transform = renderTreeParameters->transformParams,
|
||||
if (renderSource->isEnabled()) {
|
||||
renderSource->prepare({.transform = renderTreeParameters->transformParams,
|
||||
.debugOptions = updateParameters->debugOptions,
|
||||
.imageManager = *imageManager});
|
||||
.imageManager = *imageManager,
|
||||
.sourceName = name});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
const TransformParameters& transform;
|
||||
const MapDebugOptions& debugOptions;
|
||||
const ImageManager& imageManager;
|
||||
const std::string sourceName;
|
||||
};
|
||||
|
||||
using RenderTiles = std::shared_ptr<const std::vector<std::reference_wrapper<const RenderTile>>>;
|
||||
|
||||
@@ -120,8 +120,13 @@ void RenderTile::prepare(const SourcePrepareParameters& parameters) {
|
||||
(!debugBucket || debugBucket->renderable != tile.isRenderable() || debugBucket->complete != tile.isComplete() ||
|
||||
!(debugBucket->modified == tile.modified) || !(debugBucket->expires == tile.expires) ||
|
||||
debugBucket->debugMode != parameters.debugOptions)) {
|
||||
debugBucket = std::make_unique<DebugBucket>(
|
||||
tile.id, tile.isRenderable(), tile.isComplete(), tile.modified, tile.expires, parameters.debugOptions);
|
||||
debugBucket = std::make_unique<DebugBucket>(tile.id,
|
||||
tile.isRenderable(),
|
||||
tile.isComplete(),
|
||||
tile.modified,
|
||||
tile.expires,
|
||||
parameters.debugOptions,
|
||||
parameters.sourceName);
|
||||
} else if (parameters.debugOptions == MapDebugOptions::NoDebug) {
|
||||
debugBucket.reset();
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
|
||||
std::unique_ptr<gl::ProgramBase<Name>> programBase;
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility) We don't want to list every derived class as a friend
|
||||
Program([[maybe_unused]] const ProgramParameters& programParameters) {
|
||||
switch (gfx::Backend::GetType()) {
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
|
||||
#include <mapbox/eternal.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
namespace expression {
|
||||
|
||||
namespace {
|
||||
/*
|
||||
Represents the parameter list for an expression that takes an arbitrary
|
||||
number of arguments (of a specific type).
|
||||
@@ -39,7 +41,7 @@ struct Varargs : std::vector<T> {
|
||||
explicit Varargs(Args&&... args)
|
||||
: std::vector<T>(std::forward<Args>(args)...) {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
namespace detail {
|
||||
// Base class for the Signature<Fn> structs that are used to determine
|
||||
// each CompoundExpression definition's type::Type data from the type of its
|
||||
@@ -225,16 +227,17 @@ struct SignatureType<Lambda, std::enable_if_t<std::is_class_v<Lambda>>> {
|
||||
using Type = typename SignatureType<decltype(&Lambda::operator())>::Type;
|
||||
};
|
||||
|
||||
namespace {
|
||||
template <typename Fn>
|
||||
static std::unique_ptr<detail::SignatureBase> makeSignature(std::string name,
|
||||
Fn evaluateFunction,
|
||||
Dependency dependencies = Dependency::None) {
|
||||
std::unique_ptr<detail::SignatureBase> makeSignature(std::string name,
|
||||
Fn evaluateFunction,
|
||||
Dependency dependencies = Dependency::None) {
|
||||
return std::make_unique<Signature<typename SignatureType<Fn>::Type>>(
|
||||
evaluateFunction, std::move(name), dependencies);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace detail
|
||||
|
||||
namespace {
|
||||
Value featureIdAsExpressionValue(const EvaluationContext& params) {
|
||||
assert(params.feature);
|
||||
auto id = params.feature->getID();
|
||||
@@ -297,17 +300,17 @@ std::optional<std::string> featureIdAsString(const EvaluationContext& params) {
|
||||
};
|
||||
|
||||
const auto& eCompoundExpression() {
|
||||
static auto signature = detail::makeSignature("e", []() -> Result<double> { return 2.718281828459045; });
|
||||
static auto signature = detail::makeSignature("e", []() -> Result<double> { return std::numbers::e; });
|
||||
return signature;
|
||||
}
|
||||
|
||||
const auto& piCompoundExpression() {
|
||||
static auto signature = detail::makeSignature("pi", []() -> Result<double> { return 3.141592653589793; });
|
||||
static auto signature = detail::makeSignature("pi", []() -> Result<double> { return std::numbers::pi; });
|
||||
return signature;
|
||||
}
|
||||
|
||||
const auto& ln2CompoundExpression() {
|
||||
static auto signature = detail::makeSignature("ln2", []() -> Result<double> { return 0.6931471805599453; });
|
||||
static auto signature = detail::makeSignature("ln2", []() -> Result<double> { return std::numbers::ln2; });
|
||||
return signature;
|
||||
}
|
||||
|
||||
@@ -956,8 +959,8 @@ const auto& filterTypeInCompoundExpression() {
|
||||
"filter-type-in",
|
||||
[](const EvaluationContext& params, const Varargs<std::string>& types) -> Result<bool> {
|
||||
assert(params.feature);
|
||||
std::optional<std::string> type = featureTypeAsString(params.feature->getType());
|
||||
return std::find(types.begin(), types.end(), type) != types.end();
|
||||
const auto type = featureTypeAsString(params.feature->getType());
|
||||
return std::ranges::find(types, type) != types.end();
|
||||
},
|
||||
Dependency::Feature);
|
||||
return signature;
|
||||
@@ -967,8 +970,8 @@ const auto& filterIdInCompoundExpression() {
|
||||
static auto signature = detail::makeSignature(
|
||||
"filter-id-in",
|
||||
[](const EvaluationContext& params, const Varargs<Value>& ids) -> Result<bool> {
|
||||
auto id = featureIdAsExpressionValue(params);
|
||||
return std::find(ids.begin(), ids.end(), id) != ids.end();
|
||||
const auto id = featureIdAsExpressionValue(params);
|
||||
return std::ranges::find(ids, id) != ids.end();
|
||||
},
|
||||
Dependency::Feature);
|
||||
return signature;
|
||||
@@ -1113,9 +1116,9 @@ std::string expectedTypesError(const Definitions& definitions, const std::vector
|
||||
return "Expected arguments of type " + signatures + ", but found (" + actualTypes + ") instead.";
|
||||
}
|
||||
|
||||
static ParseResult createCompoundExpression(const Definitions& definitions,
|
||||
std::vector<std::unique_ptr<Expression>> args,
|
||||
ParsingContext& ctx) {
|
||||
ParseResult createCompoundExpression(const Definitions& definitions,
|
||||
std::vector<std::unique_ptr<Expression>> args,
|
||||
ParsingContext& ctx) {
|
||||
ParsingContext signatureContext(ctx.getKey());
|
||||
|
||||
for (auto it = definitions.first; it != definitions.second; ++it) {
|
||||
@@ -1162,6 +1165,8 @@ static ParseResult createCompoundExpression(const Definitions& definitions,
|
||||
return ParseResult();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ParseResult parseCompoundExpression(const std::string& name, const Convertible& value, ParsingContext& ctx) {
|
||||
assert(isArray(value) && arrayLength(value) > 0);
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ using namespace std::numbers;
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
static double signedArea(const GeometryCoordinates& ring) {
|
||||
namespace {
|
||||
double signedArea(const GeometryCoordinates& ring) {
|
||||
double sum = 0;
|
||||
|
||||
for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) {
|
||||
@@ -32,7 +33,7 @@ static double signedArea(const GeometryCoordinates& ring) {
|
||||
return sum;
|
||||
}
|
||||
|
||||
static LinearRing<int32_t> toWagyuPath(const GeometryCoordinates& ring) {
|
||||
LinearRing<int32_t> toWagyuPath(const GeometryCoordinates& ring) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
LinearRing<int32_t> result;
|
||||
@@ -43,7 +44,7 @@ static LinearRing<int32_t> toWagyuPath(const GeometryCoordinates& ring) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static GeometryCollection toGeometryCollection(MultiPolygon<int16_t>&& multipolygon) {
|
||||
GeometryCollection toGeometryCollection(MultiPolygon<int16_t>&& multipolygon) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
GeometryCollection result;
|
||||
@@ -54,6 +55,7 @@ static GeometryCollection toGeometryCollection(MultiPolygon<int16_t>&& multipoly
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
GeometryCollection fixupPolygons(const GeometryCollection& rings) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
@@ -47,9 +47,8 @@ TileLoader<T>::TileLoader(T& tile_,
|
||||
// initial std::optional part of the request.
|
||||
loadFromCache();
|
||||
} else if (necessity == TileNecessity::Required) {
|
||||
// When the file source doesn't support cache-only requests, and we
|
||||
// definiitely need this data, we can start out with a network request
|
||||
// immediately.
|
||||
// When the file source doesn't support cache-only requests, and we definitely
|
||||
// need this data, we can start out with a network request immediately.
|
||||
loadFromNetwork();
|
||||
} else {
|
||||
// When the FileSource doesn't support cache-only requests, we do
|
||||
|
||||
@@ -49,9 +49,9 @@ void scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine& scanLine)
|
||||
// scan lines!
|
||||
const double m0 = e0.dx / e0.dy;
|
||||
const double m1 = e1.dx / e1.dy;
|
||||
const double d0 = e0.dx > 0; // use y + 1 to compute x0
|
||||
const double d1 = e1.dx < 0; // use y + 1 to compute x1
|
||||
for (double y = y0; y < y1; y++) {
|
||||
const double d0 = e0.dx > 0; // use y + 1 to compute x0
|
||||
const double d1 = e1.dx < 0; // use y + 1 to compute x1
|
||||
for (double y = y0; y < y1; y++) { // NOLINT(clang-analyzer-security.FloatLoopCounter)
|
||||
double x0 = m0 * ::fmax(0, ::fmin(e0.dy, y + d0 - e0.y0)) + e0.x0;
|
||||
double x1 = m1 * ::fmax(0, ::fmin(e1.dy, y + d1 - e1.y0)) + e1.x0;
|
||||
scanLine(static_cast<int32_t>(std::floor(x1)), static_cast<int32_t>(std::ceil(x0)), static_cast<int32_t>(y));
|
||||
|
||||
Reference in New Issue
Block a user