diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index a26ad33a352..c121ca7bc01 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -212,6 +212,18 @@ jobs: working-directory: test/android steps: + - name: Free Disk Space (Ubuntu) + if: startsWith(runner.name, 'GitHub Actions') + uses: jlumbroso/free-disk-space@main + with: + tool-cache: false + android: false + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: false + - uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index 6fa39007aa2..35594f091c8 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -2,19 +2,10 @@ name: android-release on: workflow_dispatch: - inputs: - renderer: - description: "Select renderering backend" - required: true - default: "OpenGL" - type: choice - options: - - OpenGL - - Vulkan jobs: build: - runs-on: ubuntu-24.04 + runs-on: MapLibre_Native_Ubuntu_24_04_x84_16_core defaults: run: working-directory: platform/android @@ -28,17 +19,6 @@ jobs: submodules: recursive fetch-depth: 0 - - name: Map renderer input - id: backend_lowercase - run: | - if [ "${{ github.event.inputs.renderer }}" = "OpenGL" ]; then - echo "backend_lowercase=drawable" >> "$GITHUB_ENV" - elif [ "${{ github.event.inputs.renderer }}" = "Vulkan" ]; then - echo "backend_lowercase=vulkan" >> "$GITHUB_ENV" - fi - - - run: echo "cmake.dir=$(dirname "$(dirname "$(command -v cmake)")")" >> local.properties - - uses: actions/setup-java@v4 with: distribution: "temurin" @@ -65,6 +45,7 @@ jobs: - name: Update version name run: | RELEASE_VERSION="$( git describe --tags --match=android-v*.*.* --abbrev=0 | sed 's/^android-v//' )" + echo version="$RELEASE_VERSION" >> "$GITHUB_ENV" echo "Latest version from tag: $RELEASE_VERSION" if [ -n "$RELEASE_VERSION" ]; then sed -i -e "s/^VERSION_NAME=.*/VERSION_NAME=${RELEASE_VERSION}/" MapLibreAndroid/gradle.properties @@ -74,20 +55,9 @@ jobs: shell: bash - name: Build package - run: make apackage - env: - RENDERER: ${{ env.backend_lowercase }} - - - name: Build release Test App run: | - MAPLIBRE_DEVELOPER_CONFIG_XML='${{ secrets.MAPLIBRE_DEVELOPER_CONFIG_XML }}' - if [ -n "${MAPLIBRE_DEVELOPER_CONFIG_XML}" ]; then - echo "${MAPLIBRE_DEVELOPER_CONFIG_XML}" > MapLibreAndroidTestApp/src/main/res/values/developer-config.xml - make android - else - echo "No secrets.MAPLIBRE_DEVELOPER_CONFIG_XML variable set, skipping apk build..." - fi - shell: bash + RENDERER=vulkan make apackage + RENDERER=drawable make apackage # create github release - name: Prepare release @@ -99,15 +69,15 @@ jobs: echo version_tag="$( git describe --tags --match=android-v*.*.* --abbrev=0 )" >> "$GITHUB_OUTPUT" shell: bash - - name: Check if version is valid semver + - name: Check if version is pre-release id: check_version run: | - version_tag="${{ steps.prepare_release.outputs.version_tag }}" - if [[ $version_tag =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Valid semver: $version_tag" + version="${{ env.version }}" + if [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Valid semver: $version" echo "prerelease=false" >> "$GITHUB_ENV" else - echo "Invalid semver: $version_tag" + echo "Invalid semver: $version" echo "prerelease=true" >> "$GITHUB_ENV" fi @@ -123,25 +93,44 @@ jobs: draft: false prerelease: ${{ env.prerelease }} - - name: Upload aar - id: upload-release-asset + - name: Upload aar (OpenGL) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-${{ env.backend_lowercase }}-release.aar + asset_path: platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-drawable-release.aar asset_name: MapLibreAndroid-release.aar asset_content_type: application/zip - - name: Upload debug symbols + - name: Upload aar (Vulkan) + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: platform/android/MapLibreAndroid/build/outputs/aar/MapLibreAndroid-vulkan-release.aar + asset_name: MapLibreAndroid-release-vulkan.aar + asset_content_type: application/zip + + - name: Upload debug symbols (OpenGL) + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: platform/android/build/debug-symbols-opengl.tar.gz + asset_name: debug-symbols-maplibre-android-opengl-${{ steps.prepare_release.outputs.version_tag }}.tar.gz + asset_content_type: application/gzip + + - name: Upload debug symbols (Vulkan) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: platform/android/build/debug-symbols.tar.gz - asset_name: debug-symbols.tar.gz + asset_path: platform/android/build/debug-symbols-vulkan.tar.gz + asset_name: debug-symbols-maplibre-android-vulkan-${{ steps.prepare_release.outputs.version_tag }}.tar.gz asset_content_type: application/gzip - name: Clean release @@ -164,4 +153,3 @@ jobs: SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} - RENDERER: ${{ env.backend_lowercase }} diff --git a/.github/workflows/gh-pages-android-api.yml b/.github/workflows/gh-pages-android-api.yml index abe4b3fc690..5f327f21091 100644 --- a/.github/workflows/gh-pages-android-api.yml +++ b/.github/workflows/gh-pages-android-api.yml @@ -26,7 +26,7 @@ jobs: run: ./gradlew dokkaGenerate - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@v4.6.9 + uses: JamesIves/github-pages-deploy-action@v4.7.2 with: branch: gh-pages folder: platform/android/MapLibreAndroid/build/dokka/html diff --git a/.github/workflows/gh-pages-android-examples.yml b/.github/workflows/gh-pages-android-examples.yml index 5ebde8efcd0..090401df1a6 100644 --- a/.github/workflows/gh-pages-android-examples.yml +++ b/.github/workflows/gh-pages-android-examples.yml @@ -23,7 +23,7 @@ jobs: run: make mkdocs-build - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@v4.6.9 + uses: JamesIves/github-pages-deploy-action@v4.7.2 with: branch: gh-pages folder: platform/android/site diff --git a/.github/workflows/gh-pages-cpp-api.yml b/.github/workflows/gh-pages-cpp-api.yml index f2e9efa39a5..1095e1fbad3 100644 --- a/.github/workflows/gh-pages-cpp-api.yml +++ b/.github/workflows/gh-pages-cpp-api.yml @@ -20,7 +20,7 @@ jobs: run: doxygen - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@v4.6.9 + uses: JamesIves/github-pages-deploy-action@v4.7.2 with: branch: gh-pages folder: docs/doxygen/html diff --git a/.github/workflows/gh-pages-mdbook.yml b/.github/workflows/gh-pages-mdbook.yml index cb76f166427..1ebce477a66 100644 --- a/.github/workflows/gh-pages-mdbook.yml +++ b/.github/workflows/gh-pages-mdbook.yml @@ -41,7 +41,7 @@ jobs: name: book path: artifacts/book - name: Deploy - uses: JamesIves/github-pages-deploy-action@v4.6.9 + uses: JamesIves/github-pages-deploy-action@v4.7.2 with: branch: gh-pages folder: artifacts/book diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml index 7310a6f3bb8..f838c023f09 100644 --- a/.github/workflows/ios-ci.yml +++ b/.github/workflows/ios-ci.yml @@ -201,7 +201,7 @@ jobs: - name: Deploy DocC documentation (main) 🚀 if: github.ref == 'refs/heads/main' - uses: JamesIves/github-pages-deploy-action@v4.6.9 + uses: JamesIves/github-pages-deploy-action@v4.7.2 continue-on-error: true with: branch: gh-pages diff --git a/.github/workflows/windows-ci.yml b/.github/workflows/windows-ci.yml index d00231ebeba..4e3f479aae5 100644 --- a/.github/workflows/windows-ci.yml +++ b/.github/workflows/windows-ci.yml @@ -87,7 +87,7 @@ jobs: core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); - - uses: mozilla-actions/sccache-action@v0.0.6 + - uses: mozilla-actions/sccache-action@v0.0.7 - name: Initialize sccache run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 28f89bb74d6..5482b7ab088 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: actionlint additional_dependencies: [shellcheck-py] - repo: https://github.com/nicklockwood/SwiftFormat - rev: "0.55.2" + rev: "0.55.3" hooks: - id: swiftformat args: [--swiftversion, "5.8"] diff --git a/README.md b/README.md index 8fa6c7a213a..26df2071c1f 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ class MainActivity : AppCompatActivity() { ``` -For more information, refer to the [Android API Documentation](https://maplibre.org/maplibre-native/android/api/), [Android Examples Documentation](https://maplibre.org/maplibre-native/docs/book/android/getting-started-guide.html) or the [MapLibre Native Android `README.md`](platform/android/README.md). +For more information, refer to the [Android API Documentation](https://maplibre.org/maplibre-native/android/api/), [Android Examples Documentation](https://maplibre.org/maplibre-native/android/examples/getting-started/) or the [MapLibre Native Android `README.md`](platform/android/README.md). ## iOS @@ -213,7 +213,7 @@ xed platform/ios/MapLibre.xcodeproj To generate and open the Xcode project. -More information: [`platform/android/CONTRIBUTING.md`](platform/ios/CONTRIBUTING.md). +More information: [`platform/ios/CONTRIBUTING.md`](platform/ios/CONTRIBUTING.md). ## Other Platforms diff --git a/benchmark/android/gradle/wrapper/gradle-wrapper.properties b/benchmark/android/gradle/wrapper/gradle-wrapper.properties index c1d5e018598..e0fd02028bc 100644 --- a/benchmark/android/gradle/wrapper/gradle-wrapper.properties +++ b/benchmark/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/benchmark/android/gradlew b/benchmark/android/gradlew index f5feea6d6b1..f3b75f3b0d4 100755 --- a/benchmark/android/gradlew +++ b/benchmark/android/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/bin/render.cpp b/bin/render.cpp index 26e1fa11ba0..6520f7baff1 100644 --- a/bin/render.cpp +++ b/bin/render.cpp @@ -38,6 +38,9 @@ int main(int argc, char* argv[]) { args::ValueFlag widthValue(argumentParser, "pixels", "Image width", {'w', "width"}); args::ValueFlag heightValue(argumentParser, "pixels", "Image height", {'h', "height"}); + args::ValueFlag mapModeValue( + argumentParser, "MapMode", "Map mode (e.g. 'static', 'tile', 'continuous')", {'m', "mode"}); + try { argumentParser.ParseCLI(argc, argv); } catch (const args::Help&) { @@ -79,18 +82,26 @@ int main(int argc, char* argv[]) { util::RunLoop loop; + MapMode mapMode = MapMode::Static; + if (mapModeValue) { + const auto modeStr = args::get(mapModeValue); + if (modeStr == "tile") { + mapMode = MapMode::Tile; + } else if (modeStr == "continuous") { + mapMode = MapMode::Continuous; + } + } + HeadlessFrontend frontend({width, height}, static_cast(pixelRatio)); - Map map(frontend, - MapObserver::nullObserver(), - MapOptions() - .withMapMode(MapMode::Static) - .withSize(frontend.getSize()) - .withPixelRatio(static_cast(pixelRatio)), - ResourceOptions() - .withCachePath(cache_file) - .withAssetPath(asset_root) - .withApiKey(apikey) - .withTileServerOptions(mapTilerConfiguration)); + Map map( + frontend, + MapObserver::nullObserver(), + MapOptions().withMapMode(mapMode).withSize(frontend.getSize()).withPixelRatio(static_cast(pixelRatio)), + ResourceOptions() + .withCachePath(cache_file) + .withAssetPath(asset_root) + .withApiKey(apikey) + .withTileServerOptions(mapTilerConfiguration)); if (style.find("://") == std::string::npos) { style = std::string("file://") + style; diff --git a/include/mbgl/vulkan/context.hpp b/include/mbgl/vulkan/context.hpp index e17160d6589..08e439df3f6 100644 --- a/include/mbgl/vulkan/context.hpp +++ b/include/mbgl/vulkan/context.hpp @@ -146,7 +146,7 @@ class Context final : public gfx::Context { void enqueueDeletion(std::function&& function); void submitOneTimeCommand(const std::function& function) const; - void requestSurfaceUpdate() { surfaceUpdateRequested = true; } + void requestSurfaceUpdate(bool useDelay = true); private: struct FrameResources { @@ -197,6 +197,7 @@ class Context final : public gfx::Context { uint8_t frameResourceIndex = 0; std::vector frameResources; bool surfaceUpdateRequested{false}; + int32_t surfaceUpdateLatency{0}; int32_t currentFrameCount{0}; struct { diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 0c26f69f5cf..2bedb5be327 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -1,11 +1,45 @@ # Changelog MapLibre Native for Android -## main +## 11.7.1 + +> [!NOTE] +> We are now releasing OpenGL ES and Vulkan variants of MapLibre Android. See the [11.7.0 release notes](https://github.com/maplibre/maplibre-native/releases/tag/android-v11.7.0) for details. ### ✨ Features and improvements +- Batch up scheduling of deferred deletions ([#3030](https://github.com/maplibre/maplibre-native/pull/3030)). +- Specify Vulkan version needed in AndroidManifest.xml ([#3095](https://github.com/maplibre/maplibre-native/pull/3095)). + ### 🐞 Bug fixes +- Remove `Pass3D` ([#3077](https://github.com/maplibre/maplibre-native/pull/3077)). + Fixes issue where filters applied to fill extrusion layers are not rendered unless a manual zoom is applied to the map ([#3039](https://github.com/maplibre/maplibre-native/issues/3039)). + +## 11.7.0 + +This release marks the official release of MapLibre Android with Vulkan support. [Vulkan](https://www.vulkan.org) is a modern graphics API which brings advantages such as improved performance, improved observability and better stability. Specifically, starting with this version we are releasing multiple versions of MapLibre Android: + +- `org.maplibre.gl:android-sdk` (still OpenGL ES for now, might default to another rendering backend or might choose depending on device support in a future major release). +- `org.maplibre.gl:android-sdk-opengl` (OpenGL ES). +- `org.maplibre.gl:android-sdk-vulkan` (Vulkan). + +Stability has proven to be excellent, but there are a few [known issues with Vulkan](https://github.com/maplibre/maplibre-native/issues?q=is%3Aissue%20state%3Aopen%20label%3AVulkan%20type%3ABug) that will be addressed in a future update. + +Currently it is not possible to choose a backend at runtime. If you care about supporting devices that only support OpenGL ES and you want to use Vulkan, you will need to produce and ship [multiple APKs](https://developer.android.com/google/play/publishing/multiple-apks). Please see [this issue](https://github.com/maplibre/maplibre-native/issues/3079) if you are interested in choosing a rendering backend during initialization. + +Thanks to everyone who helped test the pre-releases! + +### ✨ Features and improvements + +- Fix the issue that the empty polyline cannot be updated ([#3046](https://github.com/maplibre/maplibre-native/pull/3046)). +- feat: add `getZoom` and `setZoom` function support for Android Auto ([#3037](https://github.com/maplibre/maplibre-native/pull/3037)). +- Use MapLibre Android as attribution string across languages ([#3080](https://github.com/maplibre/maplibre-native/pull/3080)). +- Use CMake 3.24.0+ for Android ([#3065](https://github.com/maplibre/maplibre-native/pull/3065)). + +### 🐞 Bug fixes + +- Fix crash on unsupported attribute type conversion ([#3066](https://github.com/maplibre/maplibre-native/pull/3066)). + ## 11.6.1 ### 🐞 Bug fixes diff --git a/platform/android/Makefile b/platform/android/Makefile index c1621751f82..8b1a85738e8 100644 --- a/platform/android/Makefile +++ b/platform/android/Makefile @@ -223,6 +223,8 @@ run-android-unit-test: run-android-unit-test-%: $(MLN_ANDROID_GRADLE) -Pmaplibre.abis=none :MapLibreAndroid:testLegacyDebugUnitTest --info --tests "$*" +DEBUG_TAR_FILE_NAME := $(if $(findstring drawable,$(RENDERER)),debug-symbols-opengl.tar.gz,debug-symbols-$(RENDERER).tar.gz) + # Builds a release package and .tar.gz with debug symbols of the Android SDK .PHONY: apackage apackage: @@ -230,7 +232,7 @@ apackage: make android-lib-arm-v7 && make android-lib-arm-v8 && make android-lib-x86 && make android-lib-x86-64 $(MLN_ANDROID_GRADLE) -Pmaplibre.abis=all assemble$(RENDERER)$(BUILDTYPE) mkdir -p build - tar -czvf build/debug-symbols.tar.gz -C MapLibreAndroid/build/intermediates/library_jni/*/*JniLibsProjectOnly/jni . + tar -czvf build/$(DEBUG_TAR_FILE_NAME) -C MapLibreAndroid/build/intermediates/library_jni/$(RENDERER)Release/*JniLibsProjectOnly/jni . # Build test app instrumentation tests apk and test app apk for all abi's .PHONY: android-ui-test @@ -245,7 +247,7 @@ run-android-test-app-center: # Uploads the compiled Android SDK to Maven Central Staging .PHONY: run-android-publish run-android-publish: - $(MLN_ANDROID_GRADLE_SINGLE_JOB)-Pmaplibre.abis=all :MapLibreAndroid:publishReleasePublicationToSonatypeRepository closeAndReleaseSonatypeStagingRepository + $(MLN_ANDROID_GRADLE_SINGLE_JOB)-Pmaplibre.abis=all :MapLibreAndroid:publishAllPublicationsToSonatypeRepository closeAndReleaseSonatypeStagingRepository # Dump system graphics information for the test app .PHONY: android-gfxinfo diff --git a/platform/android/MapLibreAndroid/gradle.properties b/platform/android/MapLibreAndroid/gradle.properties index d993d913a91..93fed717d85 100644 --- a/platform/android/MapLibreAndroid/gradle.properties +++ b/platform/android/MapLibreAndroid/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=11.6.1 +VERSION_NAME=11.7.1 # Only build native dependencies for the current ABI # See https://code.google.com/p/android/issues/detail?id=221098#c20 diff --git a/platform/android/MapLibreAndroid/src/drawable/AndroidManifest.xml b/platform/android/MapLibreAndroid/src/drawable/AndroidManifest.xml new file mode 100644 index 00000000000..6ea1b76300b --- /dev/null +++ b/platform/android/MapLibreAndroid/src/drawable/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/AndroidManifest.xml b/platform/android/MapLibreAndroid/src/main/AndroidManifest.xml index d5e48eb75d0..e33d8ddcd70 100644 --- a/platform/android/MapLibreAndroid/src/main/AndroidManifest.xml +++ b/platform/android/MapLibreAndroid/src/main/AndroidManifest.xml @@ -1,8 +1,4 @@ - - diff --git a/platform/android/MapLibreAndroid/src/main/res/values-bg/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-bg/strings.xml index ab1818f4f06..dfdefd7dd23 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-bg/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-bg/strings.xml @@ -4,7 +4,7 @@ Иконка функции. Активирай, за да покажеш диалог функции. Изглед локация. Това показва местоположението ти на картата. Показва карта създадена с MapLibre. Скролни с два пръста. Мащабирай с два пръста. - MapLibre Android SDK + MapLibre Android Предоставените OfflineRegionDefinition не пасват в границите на света: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-ca/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-ca/strings.xml index e0e4e250a21..34f4c081a4d 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-ca/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-ca/strings.xml @@ -4,7 +4,7 @@ Icona d’atribució. Activa per mostrar el diàleg de l’atribució. Vista de posició. Mostra la teva posició al mapa. Mostrant un mapa creat amb MapLibre. Desplaça’t arrossegant amb dos dits. Fes zoom pessigant amb dos dits. - MapLibre Android SDK + MapLibre Android La OfflineRegionDefinition proporcionada no encaixa amb els límits del món: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-cs/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-cs/strings.xml index e9b2978f775..682fc8f8507 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-cs/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-cs/strings.xml @@ -4,7 +4,7 @@ Atributy. Zobrazit nastavení atributů. Zobrazení polohy. Zobrazit umístění na mapě. Zobrazení mapy vytvořené s MapLibre. Posunout tažením dvěma prsty. Změnit velikost roztažením dvou prstů. - MapLibre Maps SDK pro Android + MapLibre Android Na zařízení není nainstalován webový prohlížeč, webovou stránku nelze zobrazit. Pokud OfflineRegionDefinition neodpovídá hranicím: %s \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/res/values-es/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-es/strings.xml index a5f148553a8..c5f211108a1 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-es/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-es/strings.xml @@ -4,7 +4,7 @@ Ícono de atribución. Actívalo para mostrar el diálogo de atribución. Vista de ubicación. Muestra tu ubicación en el mapa. Se está mostrando un mapa creado con MapLibre. Arrastra dos dedos para desplazarte o pellizca para acercar. - MapLibre Maps SDK para Android + MapLibre Android No puede abrir la página Web porque no hay un navegador Web en el dispositivo. El parámetro OfflineRegionDefinition que se ingresó no coincide con los límites mundiales: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-fr/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-fr/strings.xml index 18d0933a381..d36c445440f 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-fr/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-fr/strings.xml @@ -4,7 +4,7 @@ Icône d’attribution. Activer pour afficher le dialogue d’attribution. Vue de géolocalisation. Ceci affiche votre localisation sur la carte. Affichage d’une carte créée avec MapLibre. Faites la glisser en traînant deux doigts. Zoomez ou dézoomez en écartant ou rapprochant deux doigts. - SDK MapLibre Maps pour Android + MapLibre Android Aucun navigateur web installé sur l’appareil, impossible d’ouvrir une page web. Le cadre OfflineRegionDefinition pour définir la région de navigation ne tient pas dans les limites du monde : %s \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/res/values-gl/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-gl/strings.xml index 94e9c0e22b9..5229b08e07b 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-gl/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-gl/strings.xml @@ -4,7 +4,7 @@ Icona de atribución. Actívaa para amosar o diálogo de atribución. Vista de ubicación. Amosa a túa ubicación no mapa. Estase a amosar un mapa feito co MapLibre. Belisca dous dedos para desprazarte ou belisca para achegar. - MapLibre Maps SDK para o Android + MapLibre Android Non podes abrir a páxina web porque non hai un navegador web no dispositivo. O parámetro OfflineRegionDefinition que se ingresou non coincide cos límites mundiais: %s \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/res/values-he/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-he/strings.xml index 1a1017456e3..cbd763af03b 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-he/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-he/strings.xml @@ -4,7 +4,7 @@ סמל שיוך. הפעל כדי להציג תיבת דו-שיח של שיוך. סמן מיקום. מציג את המיקום הנוכחי שלך על המפה. מציג מפה שנוצרה עם MapLibre. גלול באמצעות גרירה עם שתי אצבעות, זום באמצעות צביטה עם שתי אצבעות. - MapLibre Maps SDK for Android + MapLibre Android לא מותקן דפדפן אינטרנט במכשיר, לא ניתן לפתוח את דף האינטרנט. בתנאי ש- OfflineRegionDefinition אינו מתאים לגבולות העולם: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-hu/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-hu/strings.xml index 6bfa6eb0de7..d7945d6d1bf 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-hu/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-hu/strings.xml @@ -2,7 +2,7 @@ Hely nézet. Megmutatja, hol vagy a térképen. Egy MapLibre-szal készült térkép megjelenítése. Húzd két ujjadat a görgetéshez. Csippentsd össze a nagyításhoz. - MapLibre Maps SDK Androidhoz + MapLibre Android Nincs webböngésző telepítve a készüléken, nem lehet megnyitni weboldalt. A megadott OfflineRegionDefinition nem fér bele a világ kereteibe: %s \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/res/values-iw/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-iw/strings.xml index 1a1017456e3..cbd763af03b 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-iw/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-iw/strings.xml @@ -4,7 +4,7 @@ סמל שיוך. הפעל כדי להציג תיבת דו-שיח של שיוך. סמן מיקום. מציג את המיקום הנוכחי שלך על המפה. מציג מפה שנוצרה עם MapLibre. גלול באמצעות גרירה עם שתי אצבעות, זום באמצעות צביטה עם שתי אצבעות. - MapLibre Maps SDK for Android + MapLibre Android לא מותקן דפדפן אינטרנט במכשיר, לא ניתן לפתוח את דף האינטרנט. בתנאי ש- OfflineRegionDefinition אינו מתאים לגבולות העולם: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-ko/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-ko/strings.xml index 3e86536813a..59700a67136 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-ko/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-ko/strings.xml @@ -1,10 +1,10 @@ - 지도 나침반. 지도회전를 북쪽으로 재설정합니다. + 지도 나침반. 지도회전을 북쪽으로 재설정합니다. 속성 정보. 속성 대화를 표시합니다. 로케이션 뷰. 지도에서 현재 위치를 보여줍니다. - 맵박스로 생성된 지도 표시. 두 손가락으로 드래그하여 화면을 위 아래로 움직이세요. 두 손가락을 이용해 화면을 확대 축소 하세요. - 안드로이드를 위한 맵박스 맵 SDK - 웹 브라우저가 설치 되어 있지 않아, 웹 페이지를 열 수 없습니다. + MapLibre로 생성된 지도 표시. 두 손가락으로 드래그하여 화면을 위 아래로 움직이세요. 두 손가락을 이용해 화면을 확대 축소 하세요. + MapLibre Android + 웹 브라우저가 설치 되어 있지 않아서 웹 페이지를 열 수 없습니다. 제공된 오프라인지역정의가 월드바운즈에 적합하지 않습니다: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-lt/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-lt/strings.xml index 042fa1e4794..e9ebad99641 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-lt/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-lt/strings.xml @@ -4,7 +4,7 @@ Įnašo ikona. Paspausk norėdamas pamatyti dialogą su detalėmis Vartotojo vietos vaizdas. Nurodo tavo poziciją žemėlapyje Rodomas MapLibre kurtas žemėlapis. Naviguok tempdamas du pirštus. Valdyk žemėlapio pritraukimą suimdamas/atitolindamas du pirštus. - MapLibre Android SDK + MapLibre Android Pasirinktas OfflineRegionDefinition netalpa į rėžius: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-nl/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-nl/strings.xml index 4bda0d7fc4c..8f38c2ffe40 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-nl/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-nl/strings.xml @@ -4,7 +4,7 @@ Attributie icoon. Activeer voor het tonen van het attributie dialoog. Locatie Element. Dit toont jouw locatie op de map. Toont een map gemaakt met MapLibre. Scroll door het slepen met twee vingers. Zoom door vingers te nijpen. - MapLibre Android SDK + MapLibre Android Aangeleverde OfflineRegionDefinition past niet in de wereld omtrek: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-pl/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-pl/strings.xml index 8596defccbf..1c6e426f8a4 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-pl/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-pl/strings.xml @@ -4,7 +4,7 @@ Atrybucja. Aktywuj, żeby pokazać więcej informacji. Widok lokalizacji. Pokazuje twoją pozycję na mapie. Pokazuje mapę stworzoną za pomocą biblioteki MapLibre. Przesuń mapę za pomocą przeciągnięcia dwoma palcami. Przybliż za pomocą uszczypnięcia dwoma palcami. - MapLibre Maps SDK dla Androida + MapLibre Android Nie potrafię otworzyć strony, brak przeglądarki internetowej zainstalowanej na urządzeniu. Wymagany region nie mieści się w granicach świata: %s \ No newline at end of file diff --git a/platform/android/MapLibreAndroid/src/main/res/values-pt-rPT/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-pt-rPT/strings.xml index 1e4a9144524..294b562f1da 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-pt-rPT/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-pt-rPT/strings.xml @@ -4,7 +4,7 @@ Ícone de atribuição. Ativar para mostrar a janela de atribuição. Vista de localização. Isto mostra a sua localização no mapa. A mostrar um Mapa criado com MapLibre. Desloque arrastanto com 2 dedos. Zoom afastando ou aproximando os 2 dedos. - Mapas MapLibre SDK para Android + MapLibre Android Não está nenhum navegador de Internet instalado no dispositivo. Não é possível abrir a página web. O OfflineRegionDefinition não cabe nos limites do mundo: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-ru/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-ru/strings.xml index d60dbb14ee7..38fa2e908d5 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-ru/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-ru/strings.xml @@ -4,7 +4,7 @@ Значок атрибутов. Активируйте, чтобы показать диалог. Местоположение. Отображает вашу позицию на карте. Отображает карту, созданную при помощи MapLibre. Пролистывайте двумя пальцами. Меняйте масштаб сведением пальцев. - MapLibre Maps SDK для Android + MapLibre Android На устройстве нет веб-браузера, нельзя показать веб-страницу. Запрошенный OfflineRegionDefinition не входит в допустимые границы: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-sv/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-sv/strings.xml index 7f25c919b90..85d008f147c 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-sv/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-sv/strings.xml @@ -4,7 +4,7 @@ Tillskrivningsikon. Aktivera för att visa tillskrivningsdialog. Positionsvy. Denna visar din position på kartan. Visar en karta skapad med MapLibre. Scrolla genom att dra med två fingrar. Zooma genom att nypa med två fingrar. - MapLibre Maps SDK for Android + MapLibre Android Ingen webbläsare installerad på enheten. Kan inte visa sidan. Försedd OfflineRegionDefinition passar inte världens gränser: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-uk/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-uk/strings.xml index e49faa84487..c2e52eee257 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-uk/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-uk/strings.xml @@ -4,7 +4,7 @@ Значок атрибуції. Натисніть, щоб показати діалог атрибуції. Визначення положення. Показує ваше місцеположення на мапі. Показує мапи створені за допомоги MapLibre. Пересувайте мапу двома пальцями. Змінюйте масштаб стуляючи/розводячи два пальці. - MapLibre Maps SDK для Android + MapLibre Android Веб-оглядач відсутній на цьому пристрої, неможливо відкрити веб-сторінку Межі ділянки для оффлайнового користування даними за межами світу: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-vi/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-vi/strings.xml index 17c29537c7b..90d76c58a4d 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-vi/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-vi/strings.xml @@ -4,7 +4,7 @@ Biểu tượng ghi công. Kích hoạt để xem hộp thoại ghi công. Cái chỉ vị trí. Cái này chỉ vị trí của bạn trên bản đồ. Đang xem bản đồ được xây dựng dùng MapLibre. Kéo hai ngón tay để cuộn. Chụm các ngón tay lại để phóng to. Tách các ngón tay ra để thu nhỏ. - MapLibre Maps SDK cho Android + MapLibre Android Không thể mở trang Web vì thiết bị thiếu trình duyệt. OfflineRegionDefinition được cung cấp không vừa thế giới: %s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-zh-rCN/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-zh-rCN/strings.xml index 5a5a53ca3b1..f07ab5c3098 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-zh-rCN/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-zh-rCN/strings.xml @@ -4,7 +4,7 @@ Attribution图标,点击以显示attribution对话框。 定位视图,在地图上显示当前位置。 显示由MapLibre创建的地图,通过拖动两个手指来滚动,捏两个手指来放大。 - MapLibre Maps SDK for Android + MapLibre Android 设备中未安装任何浏览器,不能打开该网页 提供的OfflineRegionDefinition不符合标准地理范围:%s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-zh-rHK/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-zh-rHK/strings.xml index d3b9659f7d0..0c4ba3041cc 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-zh-rHK/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-zh-rHK/strings.xml @@ -4,7 +4,7 @@ Attribution圖標,點擊以顯示attribution對話框。 定位視圖,在地圖上顯示當前位置。 顯示由MapLibre創建的地圖,通過拖動兩個手指來滾動,捏兩個手指來放大。 - MapLibre Maps SDK for Android + MapLibre Android 設備中未安裝任何瀏覽器,不能打開該網頁 提供的OfflineRegionDefinition不符合標準地理範圍:%s diff --git a/platform/android/MapLibreAndroid/src/main/res/values-zh-rTW/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values-zh-rTW/strings.xml index d3b9659f7d0..0c4ba3041cc 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values-zh-rTW/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values-zh-rTW/strings.xml @@ -4,7 +4,7 @@ Attribution圖標,點擊以顯示attribution對話框。 定位視圖,在地圖上顯示當前位置。 顯示由MapLibre創建的地圖,通過拖動兩個手指來滾動,捏兩個手指來放大。 - MapLibre Maps SDK for Android + MapLibre Android 設備中未安裝任何瀏覽器,不能打開該網頁 提供的OfflineRegionDefinition不符合標準地理範圍:%s diff --git a/platform/android/MapLibreAndroid/src/main/res/values/strings.xml b/platform/android/MapLibreAndroid/src/main/res/values/strings.xml index c46c01795a2..e8154eb6859 100644 --- a/platform/android/MapLibreAndroid/src/main/res/values/strings.xml +++ b/platform/android/MapLibreAndroid/src/main/res/values/strings.xml @@ -4,7 +4,7 @@ Attribution icon. Activate to show attribution dialog. Location View. This shows your location on the map. Showing a Map created with MapLibre. Scroll by dragging two fingers. Zoom by pinching two fingers. - MapLibre Maps SDK for Android + MapLibre Android No web browser installed on device, can\'t open web page. Provided OfflineRegionDefinition doesn\'t fit the world bounds: %s diff --git a/platform/android/MapLibreAndroid/src/vulkan/AndroidManifest.xml b/platform/android/MapLibreAndroid/src/vulkan/AndroidManifest.xml new file mode 100644 index 00000000000..eb13ac34e2d --- /dev/null +++ b/platform/android/MapLibreAndroid/src/vulkan/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt index 117346e5694..cabaaabcd22 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/style/HeatmapLayerActivity.kt @@ -192,7 +192,7 @@ class HeatmapLayerActivity : AppCompatActivity() { // # --8<-- [start:constants] companion object { private const val EARTHQUAKE_SOURCE_URL = - "https://maplibre.org/maplibre-gl-js-docs/assets/earthquakes.geojson" + "https://maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson" private const val EARTHQUAKE_SOURCE_ID = "earthquakes" private const val HEATMAP_LAYER_ID = "earthquakes-heat" private const val HEATMAP_LAYER_SOURCE = "earthquakes" diff --git a/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties b/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties index e2847c82004..cea7a793a84 100644 --- a/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/MapLibrePlugin/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/platform/android/MapLibrePlugin/gradlew b/platform/android/MapLibrePlugin/gradlew index f5feea6d6b1..f3b75f3b0d4 100755 --- a/platform/android/MapLibrePlugin/gradlew +++ b/platform/android/MapLibrePlugin/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/platform/android/README.md b/platform/android/README.md index 49e45809647..a68bd7ced96 100644 --- a/platform/android/README.md +++ b/platform/android/README.md @@ -6,7 +6,7 @@ MapLibre Native for Android is a library for embedding interactive map views wit ## Getting Started -Visit [https://maplibre.org/maplibre-native/docs/book/android/getting-started-guide.html](https://maplibre.org/maplibre-native/docs/book/android/getting-started-guide.html) to view the Getting Started Guide for MapLibre Native for Android. +Visit [https://maplibre.org/maplibre-native/android/examples/getting-started/](https://maplibre.org/maplibre-native/android/examples/getting-started/) to view the Getting Started Guide for MapLibre Native for Android. ## Documentation diff --git a/platform/android/android.cmake b/platform/android/android.cmake index 1f4b88724a8..fbddbb2a4f0 100644 --- a/platform/android/android.cmake +++ b/platform/android/android.cmake @@ -147,6 +147,14 @@ target_include_directories( ${PROJECT_SOURCE_DIR}/src ) +# this is needed because Android is not officially supported +# https://discourse.cmake.org/t/error-when-crosscompiling-with-whole-archive-target-link/9394 +# https://cmake.org/cmake/help/latest/release/3.24.html#generator-expressions +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE +"-Wl,--whole-archive -Wl,--no-whole-archive" +) +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED True) + find_package(curl CONFIG) target_link_libraries( diff --git a/platform/android/buildSrc/src/main/kotlin/Versions.kt b/platform/android/buildSrc/src/main/kotlin/Versions.kt index 16fd70fae6b..ba52910f87a 100644 --- a/platform/android/buildSrc/src/main/kotlin/Versions.kt +++ b/platform/android/buildSrc/src/main/kotlin/Versions.kt @@ -1,4 +1,4 @@ object Versions { - const val ndkVersion ="27.0.12077973" - const val cmakeVersion = "3.18.1+" + const val ndkVersion = "27.0.12077973" + const val cmakeVersion = "3.24.0+" } \ No newline at end of file diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts index 91784526335..20ef7345923 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts @@ -1,7 +1,7 @@ extra["mapLibreArtifactGroupId"] = "org.maplibre.gl" extra["mapLibreArtifactId"] = "android-sdk" -extra["mapLibreArtifactTitle"] = "MapLibre Maps SDK for Android" -extra["mapLibreArtifactDescription"] = "MapLibre Maps SDK for Android" +extra["mapLibreArtifactTitle"] = "MapLibre Android" +extra["mapLibreArtifactDescription"] = "MapLibre Android" extra["mapLibreDeveloperName"] = "MapLibre" extra["mapLibreDeveloperId"] = "maplibre" extra["mapLibreArtifactUrl"] = "https://github.com/maplibre/maplibre-native" diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts index aff14ef5983..3058a4232f3 100644 --- a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.kotlin.dsl.get +import java.util.Locale plugins { `maven-publish` @@ -43,20 +44,24 @@ project.logger.lifecycle(project.extra["versionName"].toString()) version = project.extra["versionName"] as String group = project.extra["mapLibreArtifactGroupId"] as String -afterEvaluate { +fun configureMavenPublication( + renderer: String, + publicationName: String, + artifactIdPostfix: String, + descriptionPostfix: String, +) { publishing { publications { - create("release") { - groupId = this@afterEvaluate.group.toString() - artifactId = project.extra["mapLibreArtifactId"].toString() - version = this@afterEvaluate.version.toString() + create(publicationName) { + groupId = project.group.toString() + artifactId = "${project.extra["mapLibreArtifactId"]}$artifactIdPostfix" + version = project.version.toString() - // Conditional component selection based on environment variable - from(components[if (System.getenv("RENDERER")?.lowercase() == "vulkan") "vulkanRelease" else "drawableRelease"]) + from(components["${renderer}Release"]) pom { - name.set(project.extra["mapLibreArtifactTitle"].toString()) - description.set(project.extra["mapLibreArtifactTitle"].toString()) + name.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") + description.set("${project.extra["mapLibreArtifactTitle"]}$descriptionPostfix") url.set(project.extra["mapLibreArtifactUrl"].toString()) licenses { license { @@ -68,7 +73,7 @@ afterEvaluate { developer { id.set(project.extra["mapLibreDeveloperId"].toString()) name.set(project.extra["mapLibreDeveloperName"].toString()) - email.set("maplibre@maplibre.org") + email.set("team@maplibre.org") } } scm { @@ -80,7 +85,24 @@ afterEvaluate { } } } +} + +// workaround for https://github.com/gradle/gradle/issues/26091#issuecomment-1836156762 +// https://github.com/gradle-nexus/publish-plugin/issues/208 +tasks { + withType { + dependsOn(withType()) + } +} + +afterEvaluate { + configureMavenPublication("drawable", "opengl", "", "") + configureMavenPublication("vulkan", "vulkan", "-vulkan", "(Vulkan)") + // Right now this is the same as the first, but in the future we might release a major version + // which defaults to Vulkan (or has support for multiple backends). We will keep using only + // OpenGL ES with this artifact ID if that happens. + configureMavenPublication("drawable", "opengl2", "-opengl", " (OpenGL ES)") } diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index e2847c82004..cea7a793a84 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm index 889b1daaadf..4aa09548804 100644 --- a/platform/darwin/src/local_glyph_rasterizer.mm +++ b/platform/darwin/src/local_glyph_rasterizer.mm @@ -1,8 +1,11 @@ #include #include +#include #include #include +#include + #include #import @@ -191,16 +194,28 @@ CFDictionaryRefHandle attributes( @param font The font to apply to the codepoint. @param metrics Upon return, the metrics match the font’s metrics for the glyph representing the codepoint. + @param isBold use kCTFontBoldTrait if it is true. @returns An image containing the glyph. */ -PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics& metrics) { +PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, GlyphMetrics& metrics, BOOL isBold) { CFStringRefHandle string(CFStringCreateWithCharacters(NULL, reinterpret_cast(&glyphID), 1)); if (!string) { throw std::runtime_error("Unable to create string from codepoint"); } + // Create a bold variant of the font + CTFontRefHandle boldFont(CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, kCTFontBoldTrait, kCTFontBoldTrait)); + if (!boldFont) { + CFStringRefHandle familyNameHandle(CTFontCopyFamilyName(font)); + NSString* familyName = (__bridge NSString *)(*familyNameHandle); + std::string stdFamilyName(familyName.UTF8String); + Log::Error(Event::General, "Unable to create bold font for " + stdFamilyName); + } + + CTFontRef drawFont = isBold && boldFont ? *boldFont : font; + CFStringRef keys[] = { kCTFontAttributeName }; - CFTypeRef values[] = { font }; + CFTypeRef values[] = { drawFont }; CFDictionaryRefHandle attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, @@ -257,7 +272,7 @@ CGContextHandle context(CGBitmapContextCreate( // Mimic glyph PBF metrics. metrics.left = Glyph::borderSize; - metrics.top = 4; + metrics.top = -Glyph::borderSize; // Move the text upward to avoid clipping off descenders. CGFloat descent; @@ -265,7 +280,7 @@ CGContextHandle context(CGBitmapContextCreate( CGContextSetTextPosition(*context, 0.0, descent); CTLineDraw(*line, *context); - + return rgbaBitmap; } @@ -288,8 +303,16 @@ CGContextHandle context(CGBitmapContextCreate( } manufacturedGlyph.id = glyphID; + BOOL isBold = NO; + // Only check the first font name to detect if the user prefers using bold + if (!fontStack.empty()) { + std::string lowercaseFont = platform::lowercase(fontStack.front()); + if (lowercaseFont.find("bold") != std::string::npos && lowercaseFont.find("semibold") == std::string::npos) { + isBold = YES; + } + } - PremultipliedImage rgbaBitmap = drawGlyphBitmap(glyphID, *font, manufacturedGlyph.metrics); + PremultipliedImage rgbaBitmap = drawGlyphBitmap(glyphID, *font, manufacturedGlyph.metrics, isBold); Size size(manufacturedGlyph.metrics.width, manufacturedGlyph.metrics.height); // Copy alpha values from RGBA bitmap into the AlphaImage output diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index b49b5c50003..65ce874aee7 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -4,6 +4,12 @@ MapLibre welcomes participation and contributions from everyone. Please read [`C ## main +## 6.9.0 + +- Batch up scheduling of deferred deletions ([#3030](https://github.com/maplibre/maplibre-native/pull/3030)). +- Remove `Pass3D` ([#3077](https://github.com/maplibre/maplibre-native/pull/3077)). +- Add bold support for CJK characters ([#3069](https://github.com/maplibre/maplibre-native/pull/3069)). + ## 6.8.1 - Update Bazel dependencies ([#3000](https://github.com/maplibre/maplibre-native/pull/3000)). diff --git a/platform/ios/VERSION b/platform/ios/VERSION index 23863d3def7..6a1fccf9303 100644 --- a/platform/ios/VERSION +++ b/platform/ios/VERSION @@ -1 +1 @@ -6.8.1 \ No newline at end of file +6.9.0 \ No newline at end of file diff --git a/platform/ios/src/MLNCompassButton.mm b/platform/ios/src/MLNCompassButton.mm index 3e0597c3c33..009f37ee05a 100644 --- a/platform/ios/src/MLNCompassButton.mm +++ b/platform/ios/src/MLNCompassButton.mm @@ -124,6 +124,8 @@ - (void)showCompass:(BOOL)animated { - (void)hideCompass:(BOOL)animated { animated ? [self animateToAlpha:0] : [self setAlpha:0]; + self.isAccessibilityElement = NO; + self.accessibilityElementsHidden = YES; } - (void)animateToAlpha:(CGFloat)alpha { diff --git a/render-test/android/gradle/wrapper/gradle-wrapper.properties b/render-test/android/gradle/wrapper/gradle-wrapper.properties index c1d5e018598..e0fd02028bc 100644 --- a/render-test/android/gradle/wrapper/gradle-wrapper.properties +++ b/render-test/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/render-test/android/gradlew b/render-test/android/gradlew index f5feea6d6b1..f3b75f3b0d4 100755 --- a/render-test/android/gradlew +++ b/render-test/android/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/scripts/generate-changelog.mjs b/scripts/generate-changelog.mjs index a704b8dcd3f..c18ed107318 100755 --- a/scripts/generate-changelog.mjs +++ b/scripts/generate-changelog.mjs @@ -18,7 +18,7 @@ function getTagLastVersion() { const lastVersion = fs .readFileSync(`platform/${platform}/CHANGELOG.md`, "utf-8") .split("\n") - .filter((line) => line.startsWith("## "))[1] + .filter((line) => line.startsWith("## "))[0] .slice(3); return `${platform}-v${lastVersion}`; } diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 8243675ff74..324d196098e 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -271,7 +271,9 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( return; } - overrideAttr->setDirty(false); + if (overrideAttr) { + overrideAttr->setDirty(false); + } bindings[index] = { /*.attribute = */ {defaultAttr.getDataType(), offset}, diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index abd8740fd2e..4ffc2aa9c13 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -169,7 +169,7 @@ const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& for (std::size_t i = 0; i < count; ++i) { if (!get(attr.get(i), type, outPtr)) { // missing type conversion - assert(false); + std::fill(outPtr, outPtr + stride_, 0); } outPtr += stride_; } diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index bda207767e4..98f5f226743 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -63,9 +63,8 @@ void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& para parameters.getCrossfadeParameters(), unevaluated.evaluate(parameters, previousProperties->evaluated)); - passes = (properties->evaluated.get() > 0) - ? (RenderPass::Translucent | RenderPass::Pass3D) - : RenderPass::None; + passes = (properties->evaluated.get() > 0) ? RenderPass::Translucent + : RenderPass::None; properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); @@ -304,15 +303,12 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, const auto& evaluated = static_cast(*evaluatedProperties).evaluated; - // `passes` is set to (RenderPass::Translucent | RenderPass::Pass3D), but `render()` - // only runs on the translucent pass, so although our output is 3D, it does not render - // in the "3D pass". constexpr auto drawPass = RenderPass::Translucent; stats.drawablesRemoved += tileLayerGroup->removeDrawablesIf([&](gfx::Drawable& drawable) { // If the render pass has changed or the tile has dropped out of the cover set, remove it. const auto& tileID = drawable.getTileID(); - if (!(drawable.getRenderPass() & passes) || (tileID && !hasRenderTile(*tileID))) { + if (!(drawable.getRenderPass() & drawPass) || (tileID && !hasRenderTile(*tileID))) { return true; } return false; @@ -337,7 +333,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); - const auto* optRenderData = getRenderDataForPass(tile, passes); + const auto* optRenderData = getRenderDataForPass(tile, drawPass); if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) { removeTile(drawPass, tileID); continue; @@ -349,7 +345,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, const auto prevBucketID = getRenderTileBucketID(tileID); if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { // This tile was previously set up from a different bucket, drop and re-create any drawables for it. - removeTile(passes, tileID); + removeTile(drawPass, tileID); } setRenderTileBucketID(tileID, bucket.getID()); diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 4533e6f7549..3e79657b5bf 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -82,6 +82,7 @@ void TilePyramid::update(const std::vector>& l tiles.clear(); renderedTiles.clear(); + cache.deferPendingReleases(); return; } @@ -279,6 +280,8 @@ void TilePyramid::update(const std::vector>& l tile.usedByRenderedLayers |= tile.layerPropertiesUpdated(layerProperties); } } + + cache.deferPendingReleases(); } void TilePyramid::handleWrapJump(float lng) { diff --git a/src/mbgl/tile/tile_cache.cpp b/src/mbgl/tile/tile_cache.cpp index 2bbde03a82b..5104c3ea6ef 100644 --- a/src/mbgl/tile/tile_cache.cpp +++ b/src/mbgl/tile/tile_cache.cpp @@ -1,10 +1,22 @@ #include + #include #include + #include namespace mbgl { +TileCache::~TileCache() { + MLN_TRACE_FUNC(); + + clear(); + pendingReleases.clear(); + + std::unique_lock counterLock{deferredSignalLock}; + deferredSignal.wait(counterLock, [&]() { return deferredDeletionsPending == 0; }); +} + void TileCache::setSize(size_t size_) { MLN_TRACE_FUNC(); @@ -26,16 +38,20 @@ void TileCache::setSize(size_t size_) { } namespace { - /// This exists solely to prevent a problem where temporary lambda captures /// are retained for the duration of the scope instead of being destroyed immediately. -template struct CaptureWrapper { - CaptureWrapper(std::unique_ptr&& item_) - : item(std::move(item_)) {} + CaptureWrapper(std::vector>&& items_) + : items(items_.size()) { + std::ranges::move(items_, items.begin()); + } + CaptureWrapper(CaptureWrapper&&) = default; + + /// This copy constructor is required to build, but doesn't seem to be called. CaptureWrapper(const CaptureWrapper& other) - : item(other.item) {} - std::shared_ptr item; + : items(other.items) {} + + std::vector> items; }; } // namespace @@ -43,6 +59,25 @@ void TileCache::deferredRelease(std::unique_ptr&& tile) { MLN_TRACE_FUNC(); tile->cancel(); + pendingReleases.push_back(std::move(tile)); +} + +void TileCache::deferPendingReleases() { + MLN_TRACE_FUNC(); + + constexpr std::size_t scheduleThreshold = 1; + if (pendingReleases.size() < scheduleThreshold) { + return; + } + + // Block destruction until the cleanup task is complete + { + std::lock_guard counterLock{deferredSignalLock}; + deferredDeletionsPending++; + } + + CaptureWrapper wrap{std::move(pendingReleases)}; + pendingReleases.clear(); // The `std::function` must be created in a separate statement from the `schedule` call. // Creating a `std::function` from a lambda involves a copy, which is why we must use @@ -51,17 +86,16 @@ void TileCache::deferredRelease(std::unique_ptr&& tile) { // If this temporary outlives the `schedule` call, and the function is executed immediately // by a waiting thread and is already complete, that temporary reference ends up being the // last one and the destruction actually occurs here on this thread. - std::function func{[tile_{CaptureWrapper{std::move(tile)}}, this]() mutable { - tile_.item = {}; + std::function func{[tile_{CaptureWrapper{std::move(wrap)}}, this]() mutable { + MLN_TRACE_ZONE(deferPendingReleases lambda); + MLN_ZONE_VALUE(wrap_.releases.size()); + tile_.items.clear(); std::lock_guard counterLock(deferredSignalLock); deferredDeletionsPending--; deferredSignal.notify_all(); }}; - std::unique_lock counterLock(deferredSignalLock); - deferredDeletionsPending++; - threadPool.schedule(std::move(func)); } diff --git a/src/mbgl/tile/tile_cache.hpp b/src/mbgl/tile/tile_cache.hpp index db9f8658c46..fea185a32ba 100644 --- a/src/mbgl/tile/tile_cache.hpp +++ b/src/mbgl/tile/tile_cache.hpp @@ -18,15 +18,7 @@ class TileCache { TileCache(const TaggedScheduler& threadPool_, size_t size_ = 0) : threadPool(threadPool_), size(size_) {} - - ~TileCache() { - clear(); - - std::unique_lock counterLock(deferredSignalLock); - while (deferredDeletionsPending != 0) { - deferredSignal.wait(counterLock); - } - } + ~TileCache(); /// Change the maximum size of the cache. void setSize(size_t); @@ -43,13 +35,17 @@ class TileCache { bool has(const OverscaledTileID& key); void clear(); - /// Destroy a tile without blocking + /// Set aside a tile to be destroyed later, without blocking void deferredRelease(std::unique_ptr&&); + /// Schedule any accumulated deferred tiles to be destroyed + void deferPendingReleases(); + private: std::map> tiles; std::list orderedKeys; TaggedScheduler threadPool; + std::vector> pendingReleases; size_t deferredDeletionsPending{0}; std::mutex deferredSignalLock; std::condition_variable deferredSignal; diff --git a/src/mbgl/vulkan/context.cpp b/src/mbgl/vulkan/context.cpp index 1acb4d691d4..e3055c4054f 100644 --- a/src/mbgl/vulkan/context.cpp +++ b/src/mbgl/vulkan/context.cpp @@ -171,6 +171,19 @@ void Context::submitOneTimeCommand(const std::function(i)) .setStageFlags(stageFlags) .setDescriptorType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1)); diff --git a/src/mbgl/vulkan/descriptor_set.cpp b/src/mbgl/vulkan/descriptor_set.cpp index d8d6866e5e7..f27f0a23c3e 100644 --- a/src/mbgl/vulkan/descriptor_set.cpp +++ b/src/mbgl/vulkan/descriptor_set.cpp @@ -50,7 +50,7 @@ void DescriptorSet::createDescriptorPool(DescriptorPoolGrowable& growablePool) { const auto descriptorPoolInfo = vk::DescriptorPoolCreateInfo(poolFlags).setPoolSizes(size).setMaxSets(maxSets); growablePool.pools.emplace_back(device->createDescriptorPoolUnique(descriptorPoolInfo), maxSets); - growablePool.currentPoolIndex = growablePool.pools.size() - 1; + growablePool.currentPoolIndex = static_cast(growablePool.pools.size() - 1); }; void DescriptorSet::allocate() { @@ -73,7 +73,8 @@ void DescriptorSet::allocate() { growablePool.pools.begin(), growablePool.pools.end(), [&](const auto& p) { return !p.unusedSets.empty(); }); if (unusedPoolIt != growablePool.pools.end()) { - growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), unusedPoolIt); + growablePool.currentPoolIndex = static_cast( + std::distance(growablePool.pools.begin(), unusedPoolIt)); } else #endif { @@ -83,7 +84,8 @@ void DescriptorSet::allocate() { [&](const auto& p) { return p.remainingSets >= layouts.size(); }); if (freePoolIt != growablePool.pools.end()) { - growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), freePoolIt); + growablePool.currentPoolIndex = static_cast( + std::distance(growablePool.pools.begin(), freePoolIt)); } else { createDescriptorPool(growablePool); } @@ -161,7 +163,7 @@ void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms, .setBufferInfo(descriptorBufferInfo) .setDescriptorCount(1) .setDescriptorType(vk::DescriptorType::eUniformBuffer) - .setDstBinding(index) + .setDstBinding(static_cast(index)) .setDstSet(descriptorSets[frameIndex]); device->updateDescriptorSets(writeDescriptorSet, nullptr); @@ -197,7 +199,7 @@ void ImageDescriptorSet::update(const std::array(id)) .setDstSet(descriptorSets[frameIndex]); device->updateDescriptorSets(writeDescriptorSet, nullptr); diff --git a/test/android/app/build.gradle.kts b/test/android/app/build.gradle.kts index 59f06ff4bc1..8e4b40b4576 100644 --- a/test/android/app/build.gradle.kts +++ b/test/android/app/build.gradle.kts @@ -47,7 +47,7 @@ android { externalNativeBuild { cmake { - version = "3.18.1+" + version = "3.24.0+" path = file("../../../CMakeLists.txt") } } diff --git a/test/android/gradle/wrapper/gradle-wrapper.properties b/test/android/gradle/wrapper/gradle-wrapper.properties index c1d5e018598..e0fd02028bc 100644 --- a/test/android/gradle/wrapper/gradle-wrapper.properties +++ b/test/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/test/android/gradlew b/test/android/gradlew index f5feea6d6b1..f3b75f3b0d4 100755 --- a/test/android/gradlew +++ b/test/android/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/test/fixtures/local_glyphs/ping_fang/expected.png b/test/fixtures/local_glyphs/ping_fang/expected.png index 02848361304..9bb78c9f756 100644 Binary files a/test/fixtures/local_glyphs/ping_fang/expected.png and b/test/fixtures/local_glyphs/ping_fang/expected.png differ diff --git a/test/fixtures/local_glyphs/ping_fang_semibold/expected.png b/test/fixtures/local_glyphs/ping_fang_semibold/expected.png index 9723cc2826f..25ceda68168 100644 Binary files a/test/fixtures/local_glyphs/ping_fang_semibold/expected.png and b/test/fixtures/local_glyphs/ping_fang_semibold/expected.png differ diff --git a/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png b/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png new file mode 100644 index 00000000000..8665da2ea6e Binary files /dev/null and b/test/fixtures/local_glyphs/ping_fang_with_bold_in_style/expected.png differ diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp index 8e3235791c5..1922aacd97c 100644 --- a/test/text/local_glyph_rasterizer.test.cpp +++ b/test/text/local_glyph_rasterizer.test.cpp @@ -10,6 +10,8 @@ #include #include +#include + /* LoadLocalCJKGlyph in glyph_manager.test.cpp exercises the platform-independent part of LocalGlyphRasterizer. This test actually @@ -17,13 +19,8 @@ on. Different platforms have different default fonts, so adding a new platform requires new "expected" fixtures. - At the time of writing, we don't run `mbgl-test` on iOS or Android, so the - only supported test platform is macOS. Supporting Android would require - adding a new test case (probably using the "Droid" font family). iOS should - theoretically work -- the "PingFang" font family used below is expected to be - available on all iOS devices, and we use a relatively high image diff - tolerance (0.05) to account for small changes between the many possible - variants of the PingFang family. + At the time of writing, we don't run this test on Android, that would require + adding a new test case (probably using the "Droid" font family). */ using namespace mbgl; @@ -33,7 +30,14 @@ namespace { class LocalGlyphRasterizerTest { public: LocalGlyphRasterizerTest(const std::optional fontFamily) - : frontend(1, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, fontFamily) {} + : frontend(1, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, fontFamily) { + this->fileSource->glyphsResponse = [&](const Resource& resource) { + EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); + Response response; + response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); + return response; + }; + } util::RunLoop loop; std::shared_ptr fileSource = std::make_shared(); @@ -59,12 +63,6 @@ class LocalGlyphRasterizerTest { TEST(LocalGlyphRasterizer, PingFang) { LocalGlyphRasterizerTest test(std::string("PingFang TC")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); #if defined(__APPLE__) && !defined(__QT__) test.checkRendering("ping_fang", 0.0161); @@ -73,16 +71,19 @@ TEST(LocalGlyphRasterizer, PingFang) { #endif // defined(__APPLE__) } +TEST(LocalGlyphRasterizer, PingFangWithBoldInStyle) { + LocalGlyphRasterizerTest test(std::string("PingFang TC")); + std::stringstream ss; + ss << std::regex_replace( + util::read_file("test/fixtures/local_glyphs/mixed.json"), std::regex("NotoCJK"), "NotoCJK Bold"); + test.map.getStyle().loadJSON(ss.str()); + test.checkRendering("ping_fang_with_bold_in_style"); +} + #if !defined(__QT__) TEST(LocalGlyphRasterizer, PingFangSemibold) { LocalGlyphRasterizerTest test(std::string("PingFang TC Semibold")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("ping_fang_semibold", 0.0161); } @@ -94,13 +95,6 @@ TEST(LocalGlyphRasterizer, PingFangSemibold) { TEST(LocalGlyphRasterizer, NotoSansCJK) { LocalGlyphRasterizerTest test(std::string("Noto Sans CJK KR Regular")); - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; - test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("noto_sans_cjk_kr_regular_qt"); } @@ -110,13 +104,6 @@ TEST(LocalGlyphRasterizer, NoLocal) { // Expectation: without any local fonts set, and without any CJK glyphs // provided, the output should just contain basic latin characters. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); test.checkRendering("no_local", 0.001, 0.1); } @@ -126,13 +113,6 @@ TEST(LocalGlyphRasterizer, NoLocalWithContentInsets) { // center. Rendered text should be on the same offset and keep the same size // as with no offset. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; auto viewSize = test.frontend.getSize(); test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json")); @@ -149,13 +129,6 @@ TEST(LocalGlyphRasterizer, NoLocalWithContentInsetsAndPitch) { // center. Rendered text should be on the same offset and keep the same size // as with no offset. LocalGlyphRasterizerTest test({}); - - test.fileSource->glyphsResponse = [&](const Resource& resource) { - EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); - Response response; - response.data = std::make_shared(util::read_file("test/fixtures/resources/glyphs.pbf")); - return response; - }; auto viewSize = test.frontend.getSize(); test.map.getStyle().loadJSON(util::read_file("test/fixtures/local_glyphs/mixed.json"));