From bc025fca494c0a332e999f02d047fbe9243d4e2e Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Thu, 11 Sep 2025 16:39:58 -0700 Subject: [PATCH] Apply just the changes from the MLT branch which aren't really part of that work (#3793) --- .clang-tidy | 3 +- .github/workflows/node-ci.yml | 7 ++- .github/workflows/qt-ci.yml | 7 ++- CMakePresets.json | 3 + include/mbgl/gfx/polyline_generator.hpp | 1 - include/mbgl/gl/uniform_buffer_gl.hpp | 2 +- .../expression/format_section_override.hpp | 4 +- include/mbgl/util/bitmask_operations.hpp | 1 + include/mbgl/util/compression.hpp | 1 + include/mbgl/util/work_task_impl.hpp | 1 - .../src/mbgl/storage/http_file_source.cpp | 24 ++++---- .../src/mbgl/storage/mbtiles_file_source.cpp | 55 +++++++++---------- .../src/mbgl/storage/pmtiles_file_source.cpp | 2 +- .../default/src/mbgl/util/compression.cpp | 26 ++++++++- platform/ios/app/MBXViewController.mm | 2 +- platform/ios/ios.toolchain.cmake | 3 + platform/ios/src/MLNMapView+Impl.mm | 2 +- src/mbgl/actor/scheduler.cpp | 2 +- src/mbgl/annotation/annotation_manager.cpp | 4 +- src/mbgl/geometry/debug_font_data.hpp | 3 +- src/mbgl/geometry/line_atlas.cpp | 5 +- src/mbgl/gfx/gpu_expression.cpp | 6 +- src/mbgl/gfx/polyline_generator.cpp | 4 +- src/mbgl/gfx/rendering_stats.cpp | 3 +- src/mbgl/gfx/shader_group.cpp | 6 +- src/mbgl/gfx/shader_registry.cpp | 6 +- src/mbgl/layout/circle_layout.hpp | 2 +- src/mbgl/layout/merge_lines.cpp | 4 +- src/mbgl/layout/pattern_layout.hpp | 12 ++-- src/mbgl/layout/symbol_feature.hpp | 1 - src/mbgl/layout/symbol_layout.cpp | 4 +- src/mbgl/map/transform_state.cpp | 4 +- src/mbgl/renderer/bucket.hpp | 2 +- src/mbgl/renderer/buckets/debug_bucket.cpp | 9 ++- src/mbgl/renderer/buckets/debug_bucket.hpp | 4 +- src/mbgl/renderer/render_orchestrator.cpp | 9 +-- src/mbgl/renderer/render_source.hpp | 1 + src/mbgl/renderer/render_tile.cpp | 9 ++- src/mbgl/shaders/gl/legacy/program.hpp | 1 + .../style/expression/compound_expression.cpp | 39 +++++++------ src/mbgl/tile/geometry_tile.hpp | 1 - src/mbgl/tile/geometry_tile_data.cpp | 8 ++- src/mbgl/tile/tile_loader_impl.hpp | 5 +- src/mbgl/util/tile_cover.cpp | 6 +- 44 files changed, 181 insertions(+), 123 deletions(-) create mode 100644 platform/ios/ios.toolchain.cmake diff --git a/.clang-tidy b/.clang-tidy index 03f7c8e0a..ec0be49fd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -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: '.*' diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index 3b03c8531..d45aaac4d 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -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' diff --git a/.github/workflows/qt-ci.yml b/.github/workflows/qt-ci.yml index 490bfc28d..15527d43a 100644 --- a/.github/workflows/qt-ci.yml +++ b/.github/workflows/qt-ci.yml @@ -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' diff --git a/CMakePresets.json b/CMakePresets.json index af2d6e6cc..98fac0774 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -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", diff --git a/include/mbgl/gfx/polyline_generator.hpp b/include/mbgl/gfx/polyline_generator.hpp index bb82ff6eb..ad8fc6ab0 100644 --- a/include/mbgl/gfx/polyline_generator.hpp +++ b/include/mbgl/gfx/polyline_generator.hpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/include/mbgl/gl/uniform_buffer_gl.hpp b/include/mbgl/gl/uniform_buffer_gl.hpp index 475007f40..e44907880 100644 --- a/include/mbgl/gl/uniform_buffer_gl.hpp +++ b/include/mbgl/gl/uniform_buffer_gl.hpp @@ -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 diff --git a/include/mbgl/style/expression/format_section_override.hpp b/include/mbgl/style/expression/format_section_override.hpp index 0d9847d80..5d7969a7f 100644 --- a/include/mbgl/style/expression/format_section_override.hpp +++ b/include/mbgl/style/expression/format_section_override.hpp @@ -21,8 +21,8 @@ public: using Object = std::unordered_map; if (context.formattedSection && context.formattedSection->is()) { const auto& section = context.formattedSection->get(); - if (section.find(propertyName) != section.end()) { - return section.at(propertyName); + if (auto hit = section.find(propertyName); hit != section.end()) { + return hit->second; } } diff --git a/include/mbgl/util/bitmask_operations.hpp b/include/mbgl/util/bitmask_operations.hpp index 019331edb..750fd14f6 100644 --- a/include/mbgl/util/bitmask_operations.hpp +++ b/include/mbgl/util/bitmask_operations.hpp @@ -8,6 +8,7 @@ namespace mbgl { template constexpr Enum operator|(Enum a, Enum b) { static_assert(std::is_enum_v, "Enum must be an enum type"); + // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) return Enum(mbgl::underlying_type(a) | mbgl::underlying_type(b)); } diff --git a/include/mbgl/util/compression.hpp b/include/mbgl/util/compression.hpp index 638553240..c0cd57b1c 100644 --- a/include/mbgl/util/compression.hpp +++ b/include/mbgl/util/compression.hpp @@ -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); diff --git a/include/mbgl/util/work_task_impl.hpp b/include/mbgl/util/work_task_impl.hpp index 0710192c4..289ed0a76 100644 --- a/include/mbgl/util/work_task_impl.hpp +++ b/include/mbgl/util/work_task_impl.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include diff --git a/platform/default/src/mbgl/storage/http_file_source.cpp b/platform/default/src/mbgl/storage/http_file_source.cpp index 6bb4ff922..040c26061 100644 --- a/platform/default/src/mbgl/storage/http_file_source.cpp +++ b/platform/default/src/mbgl/storage/http_file_source.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -16,23 +17,24 @@ #include #include -#include #include #include #include #include -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(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(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 lock(resourceOptionsMutex); + std::lock_guard lock(resourceOptionsMutex); resourceOptions = options; } ResourceOptions HTTPFileSource::Impl::getResourceOptions() { - std::lock_guard lock(resourceOptionsMutex); + std::lock_guard lock(resourceOptionsMutex); return resourceOptions.clone(); } void HTTPFileSource::Impl::setClientOptions(ClientOptions options) { - std::lock_guard lock(clientOptionsMutex); + std::lock_guard lock(clientOptionsMutex); clientOptions = options; } ClientOptions HTTPFileSource::Impl::getClientOptions() { - std::lock_guard 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); diff --git a/platform/default/src/mbgl/storage/mbtiles_file_source.cpp b/platform/default/src/mbgl/storage/mbtiles_file_source.cpp index 29b9be2de..155eaf44c 100644 --- a/platform/default/src/mbgl/storage/mbtiles_file_source.cpp +++ b/platform/default/src/mbgl/storage/mbtiles_file_source.cpp @@ -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 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(0); + const auto name = q.get(0); auto val = q.get(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 x = split(entry.second, ','); - if (x.size() != 4) { + const std::vector bounds_values = split(entry.second, ','); + if (bounds_values.size() != 4) { response.error = std::make_unique(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(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()) { diff --git a/platform/default/src/mbgl/storage/pmtiles_file_source.cpp b/platform/default/src/mbgl/storage/pmtiles_file_source.cpp index 563cb088e..5f6da10f7 100644 --- a/platform/default/src/mbgl/storage/pmtiles_file_source.cpp +++ b/platform/default/src/mbgl/storage/pmtiles_file_source.cpp @@ -119,7 +119,7 @@ public: req, tileID, header.root_dir_offset, - static_cast(header.root_dir_bytes), + static_cast(header.root_dir_bytes), 0, [=, this](std::pair tileAddress, std::unique_ptr tileError) { if (tileError) { diff --git a/platform/default/src/mbgl/util/compression.cpp b/platform/default/src/mbgl/util/compression.cpp index cad08e117..953c57117 100644 --- a/platform/default/src/mbgl/util/compression.cpp +++ b/platform/default/src/mbgl/util/compression.cpp @@ -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(v[0]); + const auto byte1 = static_cast(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(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()); } diff --git a/platform/ios/app/MBXViewController.mm b/platform/ios/app/MBXViewController.mm index 4c13a767e..44aed06c4 100644 --- a/platform/ios/app/MBXViewController.mm +++ b/platform/ios/app/MBXViewController.mm @@ -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: diff --git a/platform/ios/ios.toolchain.cmake b/platform/ios/ios.toolchain.cmake new file mode 100644 index 000000000..547d170c1 --- /dev/null +++ b/platform/ios/ios.toolchain.cmake @@ -0,0 +1,3 @@ +set(CMAKE_SYSTEM_NAME iOS) +set(CMAKE_SYSTEM_VERSION 15.0) +set(CMAKE_SYSTEM_PROCESSOR arm64) diff --git a/platform/ios/src/MLNMapView+Impl.mm b/platform/ios/src/MLNMapView+Impl.mm index a01f67add..37ecfd67e 100644 --- a/platform/ios/src/MLNMapView+Impl.mm +++ b/platform/ios/src/MLNMapView+Impl.mm @@ -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(operation)) x:tile.canonical.x - y:tile.canonical.x + y:tile.canonical.y z:tile.canonical.z wrap:tile.wrap overscaledZ:tile.overscaledZ diff --git a/src/mbgl/actor/scheduler.cpp b/src/mbgl/actor/scheduler.cpp index 36eee420f..2cb05db2a 100644 --- a/src/mbgl/actor/scheduler.cpp +++ b/src/mbgl/actor/scheduler.cpp @@ -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; diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 7fc948dd1..a8072982f 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -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); diff --git a/src/mbgl/geometry/debug_font_data.hpp b/src/mbgl/geometry/debug_font_data.hpp index 4ac7eaea7..8cd3772d7 100644 --- a/src/mbgl/geometry/debug_font_data.hpp +++ b/src/mbgl/geometry/debug_font_data.hpp @@ -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) diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index 56956808a..95a373175 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -210,8 +210,9 @@ void DashPatternTexture::upload(gfx::UploadPass& uploadPass) { if (std::holds_alternative(texture)) { auto tempTexture = uploadPass.getContext().createTexture2D(); tempTexture->upload(std::get(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); } } diff --git a/src/mbgl/gfx/gpu_expression.cpp b/src/mbgl/gfx/gpu_expression.cpp index b43afc1e4..d4691e44c 100644 --- a/src/mbgl/gfx/gpu_expression.cpp +++ b/src/mbgl/gfx/gpu_expression.cpp @@ -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::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::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom))); if (index == 0) { return getColor(0); } else if (index == stopCount) { diff --git a/src/mbgl/gfx/polyline_generator.cpp b/src/mbgl/gfx/polyline_generator.cpp index 897c378bc..cd691cb5a 100644 --- a/src/mbgl/gfx/polyline_generator.cpp +++ b/src/mbgl/gfx/polyline_generator.cpp @@ -93,14 +93,14 @@ void PolylineGenerator::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; } diff --git a/src/mbgl/gfx/rendering_stats.cpp b/src/mbgl/gfx/rendering_stats.cpp index 84aa6c590..2a572c9cc 100644 --- a/src/mbgl/gfx/rendering_stats.cpp +++ b/src/mbgl/gfx/rendering_stats.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -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) { diff --git a/src/mbgl/gfx/shader_group.cpp b/src/mbgl/gfx/shader_group.cpp index e30856f71..2859d646b 100644 --- a/src/mbgl/gfx/shader_group.cpp +++ b/src/mbgl/gfx/shader_group.cpp @@ -6,7 +6,7 @@ namespace gfx { bool ShaderGroup::isShader(const std::string& shaderName) const noexcept { std::shared_lock readerLock(programLock); - return programs.find(shaderName) != programs.end(); + return programs.contains(shaderName); } const std::shared_ptr ShaderGroup::getShader(const std::string& shaderName) const noexcept { @@ -25,7 +25,7 @@ bool ShaderGroup::replaceShader(std::shared_ptr&& shader) noexcept bool ShaderGroup::replaceShader(std::shared_ptr&& shader, const std::string& shaderName) noexcept { std::unique_lock writerLock(programLock); - if (programs.find(shaderName) == programs.end()) { + if (!programs.contains(shaderName)) { return false; } @@ -39,7 +39,7 @@ bool ShaderGroup::registerShader(std::shared_ptr&& shader) noexcept bool ShaderGroup::registerShader(std::shared_ptr&& shader, const std::string& shaderName) noexcept { std::unique_lock writerLock(programLock); - if (programs.find(shaderName) != programs.end()) { + if (programs.contains(shaderName)) { return false; } diff --git a/src/mbgl/gfx/shader_registry.cpp b/src/mbgl/gfx/shader_registry.cpp index ff4ad6da6..93d012543 100644 --- a/src/mbgl/gfx/shader_registry.cpp +++ b/src/mbgl/gfx/shader_registry.cpp @@ -13,7 +13,7 @@ ShaderGroup& ShaderRegistry::getLegacyGroup() noexcept { bool ShaderRegistry::isShaderGroup(const std::string& shaderGroupName) const noexcept { std::shared_lock 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 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 writerLock(shaderGroupLock); - if (shaderGroups.find(shaderGroupName) != shaderGroups.end()) { + if (shaderGroups.contains(shaderGroupName)) { return false; } diff --git a/src/mbgl/layout/circle_layout.hpp b/src/mbgl/layout/circle_layout.hpp index e5197565b..361cda0c4 100644 --- a/src/mbgl/layout/circle_layout.hpp +++ b/src/mbgl/layout/circle_layout.hpp @@ -45,7 +45,7 @@ public: const auto& sortKeyProperty = layout.template get(); 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)); } diff --git a/src/mbgl/layout/merge_lines.cpp b/src/mbgl/layout/merge_lines.cpp index ba7e90a6c..3877c2b00 100644 --- a/src/mbgl/layout/merge_lines.cpp +++ b/src/mbgl/layout/merge_lines.cpp @@ -7,7 +7,7 @@ namespace util { // Map of key -> index into features using Index = std::unordered_map; - +namespace { size_t mergeFromRight(std::vector& features, Index& rightIndex, Index::iterator left, @@ -40,7 +40,7 @@ size_t mergeFromLeft(std::vector& features, size_t getKey(const std::u16string& text, const GeometryCoordinate& coord) { return util::hash(text, coord.x, coord.y); } - +} // namespace void mergeLines(std::vector& features) { Index leftIndex; Index rightIndex; diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index c8e362218..92c0c8ebd 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -8,6 +8,8 @@ #include #include +#include + namespace mbgl { class PatternDependency { @@ -54,8 +56,8 @@ struct PatternFeatureInserter { template static void insert(std::vector& features, std::size_t index, - std::unique_ptr feature, - PatternLayerMap patternDependencyMap, + std::unique_ptr&& feature, + PatternLayerMap&& patternDependencyMap, float /*zoom*/, const PropertiesType&, const CanonicalTileID&) { @@ -68,8 +70,8 @@ struct PatternFeatureInserter { template static void insert(std::vector& features, std::size_t index, - std::unique_ptr feature, - PatternLayerMap patternDependencyMap, + std::unique_ptr&& 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>& group, - std::unique_ptr sourceLayer_, + std::unique_ptr&& sourceLayer_, const LayoutParameters& layoutParameters) : sourceLayer(std::move(sourceLayer_)), zoom(parameters.tileID.overscaledZ), diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp index b72687cbd..303137dfe 100644 --- a/src/mbgl/layout/symbol_feature.hpp +++ b/src/mbgl/layout/symbol_feature.hpp @@ -4,7 +4,6 @@ #include #include -#include #include #include diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 902b952e0..b2168a22d 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -27,13 +27,13 @@ namespace mbgl { using namespace style; +namespace { template -static bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) { +bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) { return layout.get().match([](const typename Property::Type& t) { return !t.empty(); }, [](const auto&) { return true; }); } -namespace { expression::Value sectionOptionsToValue(const SectionOptions& options) { std::unordered_map result; // TODO: Data driven properties that can be overridden on per section basis. diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp index 773b7d843..50c075daf 100644 --- a/src/mbgl/map/transform_state.cpp +++ b/src/mbgl/map/transform_state.cpp @@ -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 p = util::interpolate(p0, p1, t) / scale * static_cast(1 << atZoom); - return {{p.x, p.y}, static_cast(atZoom)}; + return {.p = {p.x, p.y}, .z = static_cast(atZoom)}; } LatLng TransformState::screenCoordinateToLatLng(const ScreenCoordinate& point, LatLng::WrapMode wrapMode) const { diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index 11e2d214a..319a0607b 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -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&) {} diff --git a/src/mbgl/renderer/buckets/debug_bucket.cpp b/src/mbgl/renderer/buckets/debug_bucket.cpp index f2b8f3797..bacd439fb 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.cpp +++ b/src/mbgl/renderer/buckets/debug_bucket.cpp @@ -13,12 +13,14 @@ DebugBucket::DebugBucket(const OverscaledTileID& id, const bool complete_, std::optional modified_, std::optional 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; } diff --git a/src/mbgl/renderer/buckets/debug_bucket.hpp b/src/mbgl/renderer/buckets/debug_bucket.hpp index 908b69bb5..52f6cb611 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.hpp +++ b/src/mbgl/renderer/buckets/debug_bucket.hpp @@ -22,7 +22,8 @@ public: bool complete, std::optional modified, std::optional expires, - MapDebugOptions); + MapDebugOptions, + std::string sourceName); void upload(gfx::UploadPass&); @@ -31,6 +32,7 @@ public: const std::optional modified; const std::optional expires; const MapDebugOptions debugMode; + const std::string sourceName; gfx::VertexVector vertices; gfx::IndexVector indices; diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 18dcda352..6859fa425 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -428,12 +428,13 @@ std::unique_ptr 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}); } } diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index 334bd1bc8..f54ace058 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -43,6 +43,7 @@ public: const TransformParameters& transform; const MapDebugOptions& debugOptions; const ImageManager& imageManager; + const std::string sourceName; }; using RenderTiles = std::shared_ptr>>; diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index 6f0dfd817..8c1d46b35 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -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( - tile.id, tile.isRenderable(), tile.isComplete(), tile.modified, tile.expires, parameters.debugOptions); + debugBucket = std::make_unique(tile.id, + tile.isRenderable(), + tile.isComplete(), + tile.modified, + tile.expires, + parameters.debugOptions, + parameters.sourceName); } else if (parameters.debugOptions == MapDebugOptions::NoDebug) { debugBucket.reset(); } diff --git a/src/mbgl/shaders/gl/legacy/program.hpp b/src/mbgl/shaders/gl/legacy/program.hpp index 9d285499e..4a01420b8 100644 --- a/src/mbgl/shaders/gl/legacy/program.hpp +++ b/src/mbgl/shaders/gl/legacy/program.hpp @@ -45,6 +45,7 @@ public: std::unique_ptr> 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 diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index 0d0b4dbe2..1a2c1a4bf 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -14,13 +14,15 @@ #include +#include #include #include +#include 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 { explicit Varargs(Args&&... args) : std::vector(std::forward(args)...) {} }; - +} // namespace namespace detail { // Base class for the Signature structs that are used to determine // each CompoundExpression definition's type::Type data from the type of its @@ -225,16 +227,17 @@ struct SignatureType>> { using Type = typename SignatureType::Type; }; +namespace { template -static std::unique_ptr makeSignature(std::string name, - Fn evaluateFunction, - Dependency dependencies = Dependency::None) { +std::unique_ptr makeSignature(std::string name, + Fn evaluateFunction, + Dependency dependencies = Dependency::None) { return std::make_unique::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 featureIdAsString(const EvaluationContext& params) { }; const auto& eCompoundExpression() { - static auto signature = detail::makeSignature("e", []() -> Result { return 2.718281828459045; }); + static auto signature = detail::makeSignature("e", []() -> Result { return std::numbers::e; }); return signature; } const auto& piCompoundExpression() { - static auto signature = detail::makeSignature("pi", []() -> Result { return 3.141592653589793; }); + static auto signature = detail::makeSignature("pi", []() -> Result { return std::numbers::pi; }); return signature; } const auto& ln2CompoundExpression() { - static auto signature = detail::makeSignature("ln2", []() -> Result { return 0.6931471805599453; }); + static auto signature = detail::makeSignature("ln2", []() -> Result { return std::numbers::ln2; }); return signature; } @@ -956,8 +959,8 @@ const auto& filterTypeInCompoundExpression() { "filter-type-in", [](const EvaluationContext& params, const Varargs& types) -> Result { assert(params.feature); - std::optional 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& ids) -> Result { - 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> args, - ParsingContext& ctx) { +ParseResult createCompoundExpression(const Definitions& definitions, + std::vector> 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); diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index cdb25f41a..7f1731c98 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -14,7 +14,6 @@ #include #include #include -#include namespace mbgl { diff --git a/src/mbgl/tile/geometry_tile_data.cpp b/src/mbgl/tile/geometry_tile_data.cpp index 5d83504a0..d10a1938f 100644 --- a/src/mbgl/tile/geometry_tile_data.cpp +++ b/src/mbgl/tile/geometry_tile_data.cpp @@ -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 toWagyuPath(const GeometryCoordinates& ring) { +LinearRing toWagyuPath(const GeometryCoordinates& ring) { MLN_TRACE_FUNC(); LinearRing result; @@ -43,7 +44,7 @@ static LinearRing toWagyuPath(const GeometryCoordinates& ring) { return result; } -static GeometryCollection toGeometryCollection(MultiPolygon&& multipolygon) { +GeometryCollection toGeometryCollection(MultiPolygon&& multipolygon) { MLN_TRACE_FUNC(); GeometryCollection result; @@ -54,6 +55,7 @@ static GeometryCollection toGeometryCollection(MultiPolygon&& multipoly } return result; } +} // namespace GeometryCollection fixupPolygons(const GeometryCollection& rings) { MLN_TRACE_FUNC(); diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp index 10b4f5549..dd465fc94 100644 --- a/src/mbgl/tile/tile_loader_impl.hpp +++ b/src/mbgl/tile/tile_loader_impl.hpp @@ -47,9 +47,8 @@ TileLoader::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 diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index d4f2e4eab..21806a236 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -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(std::floor(x1)), static_cast(std::ceil(x0)), static_cast(y));