Merge branch 'organicmaps:master' into master

This commit is contained in:
Timmy-Tesseract 2024-01-25 18:09:01 +08:00 committed by GitHub
commit 0e161268d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5792 changed files with 862713 additions and 257137 deletions

View file

@ -4,7 +4,7 @@
BasedOnStyle: Google
IndentWidth: 2
BreakBeforeBraces: Allman
ColumnLimit: 100
ColumnLimit: 120
---
Language: Cpp
@ -21,7 +21,7 @@ IndentCaseLabels: false
NamespaceIndentation: None
PointerAlignment: Middle
SortIncludes: true
Standard: Cpp11
Standard: c++17
IncludeBlocks: Regroup
IncludeCategories:
# Tests --------------------------------------------------------------------------------------------

View file

@ -1 +1,3 @@
6aa73face8b5eb8e026cfafa40d1983d4a0502c0
480fa6c2fcf53be296504ac6ba8e6b3d70f92b42
a6ede2b1466f0c9d8a443600ef337ba6b5832e58

9
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1,9 @@
# Require legal approval for all new graphics
android/app/src/main/res/drawable*/ @organicmaps/legal
android/app/src/main/res/fonts/ @organicmaps/legal
android/app/src/main/res/mipmap*/ @organicmaps/legal
data/*.ttf @organicmaps/legal
data/resources*/ @organicmaps/legal
data/search-icons/ @organicmaps/legal
data/styles/clear/style-*/ @organicmaps/legal
iphone/Maps/Images.xcassets/ @organicmaps/legal

View file

@ -1,14 +1,17 @@
---
name: Bug Report
about: Describe your issue in details to help us improve Organic Maps
about: Describe your issue in detail to help us improve Organic Maps
title: ''
labels: ''
assignees: ''
---
⚠ Have you searched for similar, already existing issues?
**Describe the issue**
Please write here a clear and concise description of what the bug/issue is about.
Please write a clear and concise description of the issue here.
**Steps to reproduce**
1. Go to '...'
@ -16,16 +19,20 @@ Please write here a clear and concise description of what the bug/issue is about
3. Scroll down to '....'
4. See error
**Expected behavior**
**Expected behaviour**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots or screen recordings to help explain your problem.
**System information:**
- Operating system and its version: [iOS 12, Android 10, Ubuntu 22, MacOS Big Sur, etc.]
- Organic Maps version: [you can find it by clicking the "?" button]
- Device Model: [e.g. iPhone6, Samsung S22]
- Organic Maps version: [you can find it by tapping the button with the green Organic Maps logo]
- Device Model: [e.g. iPhone 6, Samsung S22]
**Additional context**
Please add any other context and important details/notes/comments about the problem here.
Please add any other context or comments here that may be useful.

View file

@ -2,10 +2,10 @@ blank_issues_enabled: true
contact_links:
- name: Discussions
url: https://github.com/organicmaps/organicmaps/discussions
about: Discuss the usage of OrganicMaps, ask questions, or talk about ideas that are not yet actionable.
about: Discuss the usage of Organic Maps, ask questions, or talk about ideas that aren't yet actionable.
- name: Translations
url: https://github.com/organicmaps/organicmaps/blob/master/docs/TRANSLATIONS.md
about: Translate Organic Maps into your language
- name: News
url: https://organicmaps.app/news/
about: Check the latest project news
about: Check the latest project news

View file

@ -1,22 +1,27 @@
---
name: Feature request
about: Suggest an idea for OrganicMaps
name: Feature Request
about: Suggest an idea for Organic Maps
title: ''
labels: [Enhancement]
assignees: ''
---
⚠ Have you searched for similar, already existing issues?
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. For example:
I'm always frustrated when [...]
**Describe the solution you would like**
**Describe the ideal solution**
A clear and concise description of what you want to see in Organic Maps.
**Describe alternatives you have considered**
- How do you solve this issue now with Organic Maps or other apps?
- Attach any examples, screenshots, or screen recordings from other apps that help us to better understand the idea.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -19,6 +19,12 @@ on:
- docs/**
- generator/**
- packaging/**
- platform/*apple*
- platform/*_ios*
- platform/*_linux*
- platform/*_mac*
- platform/*qt*
- platform/*_win*
- pyhelpers/**
- qt*/**
- skin_generator/**
@ -26,6 +32,9 @@ on:
- track_generator/**
- xcode/**
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs:
android-google-beta:
name: Android Google Beta
@ -39,7 +48,7 @@ jobs:
sudo apt-get install -y ninja-build
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 100 # enough to get all commits for the current day
@ -48,7 +57,7 @@ jobs:
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Checkout private keys
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.PRIVATE_REPO }}
ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
@ -67,7 +76,7 @@ jobs:
run: |
cmake --version
ninja --version
gradle -x lint -x lintVitalGoogleBeta assembleGoogleBeta uploadCrashlyticsSymbolFileGoogleBeta uploadCrashlyticsMappingFileGoogleBeta
./gradlew -Pfirebase -x lint -x lintVitalGoogleBeta assembleGoogleBeta uploadCrashlyticsSymbolFileGoogleBeta uploadCrashlyticsMappingFileGoogleBeta
- name: Upload beta apk to App Distribution
shell: bash

View file

@ -4,8 +4,8 @@ on:
pull_request:
paths:
- .github/workflows/android-check-metadata.yaml # Run check on self change
- android/src/fdroid/**
- android/src/google/**
- android/app/src/fdroid/**
- android/app/src/google/**
- tools/python/check_store_metadata.py
jobs:
@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Check metadata
run: ./tools/python/check_store_metadata.py android

View file

@ -1,6 +1,9 @@
name: Android Check
on:
workflow_dispatch: # Manual trigger
push:
branches:
- master
pull_request:
paths-ignore:
- .gitignore
@ -11,13 +14,19 @@ on:
- LICENSE
- NOTICE
- README.md
- android/src/fdroid/**
- android/src/google/**
- android/app/src/fdroid/**
- android/app/src/google/**
- iphone/**
- data/strings/**
- docs/**
- generator/**
- packaging/**
- platform/*apple*
- platform/*_ios*
- platform/*_linux*
- platform/*_mac*
- platform/*qt*
- platform/*_win*
- pyhelpers/**
- qt*/**
- skin_generator/**
@ -25,13 +34,16 @@ on:
- track_generator/**
- xcode/**
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs:
lint:
name: Android Lint
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1
@ -46,7 +58,7 @@ jobs:
- name: Lint
shell: bash
working-directory: android
run: gradle lint
run: ./gradlew -Pandroidauto=true lint
android-check:
name: Build Android Debug
@ -55,6 +67,10 @@ jobs:
fail-fast: false
matrix:
flavor: [WebDebug, FdroidBeta]
# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
group: ${{ github.workflow }}-${{ matrix.flavor }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Install build tools and dependencies
@ -64,7 +80,7 @@ jobs:
sudo apt-get install -y ninja-build
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 200 # enough to get all commits for the current day
@ -76,17 +92,25 @@ jobs:
shell: bash
run: ./configure.sh
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.workflow }}-${{ matrix.flavor }}
- name: Compile ${{ matrix.flavor }}
shell: bash
working-directory: android
env:
CMAKE_C_COMPILER_LAUNCHER: ccache
CMAKE_CXX_COMPILER_LAUNCHER: ccache
run: |
cmake --version
ninja --version
gradle -Parm64 assemble${{ matrix.flavor }}
./gradlew -Parm64 assemble${{ matrix.flavor }}
- name: Upload arm64-v8a ${{ matrix.flavor }} apk
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: android-arm64-v8a-${{ matrix.flavor }}
path: android/build/outputs/apk/**/OrganicMaps-*.apk
path: android/app/build/outputs/apk/**/OrganicMaps-*.apk
if-no-files-found: error

View file

@ -2,7 +2,10 @@ name: Android Monkey
on:
workflow_dispatch: # Manual trigger
schedule:
- cron: '0 5 * * *' # Once per day at 05:00 UTC
- cron: '0 5 * * 0' # Once per week at 05:00 UTC
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs:
precondition:
@ -10,7 +13,7 @@ jobs:
name: Check preconditions
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 1000 # fetch month or so
@ -45,7 +48,7 @@ jobs:
uses: google-github-actions/setup-gcloud@v0
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 100 # enough to get all commits for the current day
@ -54,7 +57,7 @@ jobs:
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Checkout private keys
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.PRIVATE_REPO }}
ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
@ -73,16 +76,17 @@ jobs:
run: |
cmake --version
ninja --version
gradle -Pfirebase assembleGoogleDebug uploadCrashlyticsSymbolFileGoogleDebug
./gradlew -Pfirebase -Parm64-v8a -Parmeabi-v7a -Px86_64 assembleGoogleDebug uploadCrashlyticsSymbolFileGoogleDebug
- name: Run monkey
run: |
gcloud auth activate-service-account --key-file android/firebase-test-lab.json
gcloud auth activate-service-account --key-file android/app/firebase-test-lab.json
gcloud config set project omapsapp
gcloud firebase test android run --app ./android/build/outputs/apk/google/debug/OrganicMaps-*-google-debug.apk \
--device model=panther,version=33 \
gcloud firebase test android run --app ./android/app/build/outputs/apk/google/debug/OrganicMaps-*-google-debug.apk \
--device model=husky,version=34 \
--device model=cheetah,version=33 \
--device model=bluejay,version=32 \
--device model=b2q,version=31 \
--device model=a51,version=31 \
--device model=f2q,version=30 \
--device model=a10,version=29 \
--device model=Pixel2.arm,version=30 \
@ -93,6 +97,4 @@ jobs:
--device model=Nexus6,version=25 \
--device model=NexusLowRes,version=24 \
--device model=NexusLowRes,version=23,orientation=landscape \
--device model=Nexus6,version=22 \
--device model=Nexus7,version=21 \
--timeout 15m

View file

@ -2,6 +2,9 @@ name: Android Release Metadata
on:
workflow_dispatch: # Manual trigger
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs:
android-release-metadata:
name: Upload Google Play metadata
@ -9,14 +12,14 @@ jobs:
environment: production
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Parallel submodules checkout
shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Checkout screenshots
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.SCREENSHOTS_REPO }}
ssh-key: ${{ secrets.SCREENSHOTS_SSH_KEY }}
@ -24,7 +27,7 @@ jobs:
path: screenshots
- name: Checkout private keys
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.PRIVATE_REPO }}
ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}

View file

@ -3,8 +3,9 @@ on:
workflow_dispatch: # Manual trigger
env:
RELEASE_NOTES: android/src/google/play/release-notes/en-US/default.txt
FDROID_VERSION: android/src/fdroid/play/version.yaml
RELEASE_NOTES: android/app/src/google/play/release-notes/en-US/default.txt
FDROID_VERSION: android/app/src/fdroid/play/version.yaml
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs:
tag:
@ -13,7 +14,7 @@ jobs:
environment: production
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 100 # Enough to get all commits for the last day.
ssh-key: ${{ secrets.RELEASE_SSH_KEY }}
@ -28,15 +29,17 @@ jobs:
version=$(tools/unix/version.sh ios_version)
# +1 because below a "Bump versions" commit is created.
# TODO: Find a way to refactor FDroid versioning without that additional commit.
build=$(($(tools/unix/version.sh ios_build) + 1))
code=$(($(tools/unix/version.sh android_code) + 1))
# build=$(($(tools/unix/version.sh ios_build) + 1))
# code=$(($(tools/unix/version.sh android_code) + 1))
build=$(tools/unix/version.sh ios_build)
code=$(tools/unix/version.sh android_code)
tag=$version-$build-android
echo "::set-output name=version::$version"
echo "::set-output name=build::$build"
echo "::set-output name=tag::$tag"
echo "::set-output name=code::$code"
echo "version: ${version}-${build}-FDroid+${code}" > ${{ env.FDROID_VERSION }}
git add ${{ env.FDROID_VERSION }}
# echo "version: ${version}-${build}-FDroid+${code}" > ${{ env.FDROID_VERSION }}
# git add ${{ env.FDROID_VERSION }}
{
echo $tag
echo
@ -44,7 +47,7 @@ jobs:
} > ${{ runner.temp }}/tag.txt
branch="${GITHUB_REF#refs/heads/}"
test -n "$branch"
git commit -m "Bump versions" -s
# git commit -m "Bump versions" -s
git tag -a $tag -F ${{ runner.temp }}/tag.txt
git show $tag
git push origin $branch:$branch
@ -75,7 +78,7 @@ jobs:
sudo apt-get install -y ninja-build
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 100 # enough to get all commits for the current day
ref: 'refs/tags/${{ needs.tag.outputs.tag }}'
@ -92,7 +95,7 @@ jobs:
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Checkout screenshots
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.SCREENSHOTS_REPO }}
ssh-key: ${{ secrets.SCREENSHOTS_SSH_KEY }}
@ -100,7 +103,7 @@ jobs:
path: screenshots
- name: Checkout private keys
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.PRIVATE_REPO }}
ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
@ -121,22 +124,22 @@ jobs:
shell: bash
working-directory: android
run: |
gradle bundleGoogleRelease publishGoogleReleaseBundle
./gradlew bundleGoogleRelease publishGoogleReleaseBundle
if: ${{ matrix.flavor == 'google' }}
- name: Compile and upload to Huawei AppGallery
shell: bash
working-directory: android
run: |
gradle bundleHuaweiRelease
gradle publishHuaweiAppGalleryHuaweiRelease
./gradlew bundleHuaweiRelease
./gradlew publishHuaweiAppGalleryHuaweiRelease
if: ${{ matrix.flavor == 'huawei' }}
- name: Compile universal APK
shell: bash
working-directory: android
run: |
gradle assembleWebRelease
./gradlew assembleWebRelease
if: ${{ matrix.flavor == 'web' }}
- name: Prepare release notes
@ -150,7 +153,7 @@ jobs:
echo ""
echo "sha256sum:"
echo -e '\n```'
(cd ./android/build/outputs/apk/web/release/ && sha256sum OrganicMaps-${{ needs.tag.outputs.code }}-web-release.apk) | tr -d '\n'
(cd ./android/app/build/outputs/apk/web/release/ && sha256sum OrganicMaps-${{ needs.tag.outputs.code }}-web-release.apk) | tr -d '\n'
echo -e '\n```'
} > ${{ runner.temp }}/release-notes.txt
@ -163,5 +166,5 @@ jobs:
name: ${{ needs.tag.outputs.tag }}
tag_name: ${{ needs.tag.outputs.tag }}
discussion_category_name: 'Announcements'
files: ./android/build/outputs/apk/web/release/OrganicMaps-${{ needs.tag.outputs.code }}-web-release.apk
files: ./android/app/build/outputs/apk/web/release/OrganicMaps-${{ needs.tag.outputs.code }}-web-release.apk
fail_on_unmatched_files: true

View file

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install appstream validator
shell: bash

34
.github/workflows/cleanup_caches.yml vendored Normal file
View file

@ -0,0 +1,34 @@
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
name: Cleanup caches by a branch
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Cleanup
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"

143
.github/workflows/coverage-check.yaml vendored Normal file
View file

@ -0,0 +1,143 @@
name: Coverage Report
on:
workflow_dispatch: # Manual trigger
pull_request:
types:
- opened
- synchronize
- labeled
- unlabeled
# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
group: ${{ github.workflow }}-coverage-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
should-run-check:
name: Should run coverage
runs-on: ubuntu-22.04
outputs:
run-from-pr: ${{ steps.run-from-pr.outputs.run-from-pr }}
manually-triggered: ${{ steps.manually-triggered.outputs.manually-triggered }}
steps:
- name: Check if PR has 'Coverage' label
id: run-from-pr
if: github.event_name == 'pull_request'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ github.token }}
run: |
LABEL_NAME="Coverage"
LABELS=$(gh pr view https://github.com/$GITHUB_REPOSITORY/pull/$PR_NUMBER --json labels)
if echo "$LABELS" | jq -e '.labels[].name' | grep -q "$LABEL_NAME"; then
echo "run-from-pr=true" >> $GITHUB_OUTPUT
echo "'Coverage' label found in PR."
fi
- name: Check if manually triggered
id: manually-triggered
if: github.event_name == 'workflow_dispatch'
run: echo "manually-triggered=true" >> $GITHUB_OUTPUT
coverage:
needs: should-run-check
name: Generate coverage report
runs-on: ubuntu-22.04
if: ${{ needs.should-run-check.outputs.run-from-pr == 'true' || needs.should-run-check.outputs.manually-triggered == 'true'}}
steps:
- name: Free disk space by removing .NET, Android and Haskell
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
- name: Checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 100 # enough to get all commits for the current day
- name: Parallel submodules checkout
shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Install build tools and dependencies
shell: bash
run: |
sudo apt update -y
sudo apt install -y \
ninja-build \
libgl1-mesa-dev \
libglvnd-dev \
qt6-base-dev \
libqt6svg6-dev \
qt6-positioning-dev \
libqt6positioning6-plugins \
libqt6positioning6 \
llvm
pip install gcovr
- name: Configure
shell: bash
run: ./configure.sh
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.workflow }}-coverage
- name: CMake
shell: bash
env:
CC: clang-14
CXX: clang++-14
CMAKE_C_COMPILER_LAUNCHER: ccache
CMAKE_CXX_COMPILER_LAUNCHER: ccache
# -g1 should slightly reduce build time.
run: |
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS=-g1 -DCOVERAGE_REPORT=ON
- name: Compile
shell: bash
working-directory: build
run: ninja
- name: Tests
shell: bash
working-directory: build
env:
# drape_tests - requires X Window
# generator_integration_tests - https://github.com/organicmaps/organicmaps/issues/225
# opening_hours_integration_tests - https://github.com/organicmaps/organicmaps/issues/219
# opening_hours_supported_features_tests - https://github.com/organicmaps/organicmaps/issues/219
# routing_integration_tests - https://github.com/organicmaps/organicmaps/issues/221
# shaders_tests - https://github.com/organicmaps/organicmaps/issues/223
# world_feed_integration_tests - https://github.com/organicmaps/organicmaps/issues/215
CTEST_EXCLUDE_REGEX: "drape_tests|generator_integration_tests|opening_hours_integration_tests|opening_hours_supported_features_tests|routing_benchmarks|routing_integration_tests|routing_quality_tests|search_quality_tests|storage_integration_tests|shaders_tests|world_feed_integration_tests"
run: |
sudo locale-gen en_US
sudo locale-gen en_US.UTF-8
sudo locale-gen es_ES
sudo locale-gen es_ES.UTF-8
sudo locale-gen fr_FR
sudo locale-gen fr_FR.UTF-8
sudo locale-gen ru_RU
sudo locale-gen ru_RU.UTF-8
sudo update-locale
ctest -L "omim-test" -E "$CTEST_EXCLUDE_REGEX" --output-on-failure
- name: Run coverage report generation
shell: bash
working-directory: build
run: |
cmake --build . --target omim_coverage
cat coverage_report/summary.txt
- name: Archive the coverage report
working-directory: build/coverage_report
run: zip -r coverage_report.zip html/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: build/coverage_report/coverage_report.zip

View file

@ -19,6 +19,11 @@ on:
- docs/**
- generator/**
- packaging/**
- platform/*_android*
- platform/*_linux*
- platform/*_mac*
- platform/*qt*
- platform/*_win*
- pyhelpers/**
- qt*/**
- skin_generator/**
@ -28,8 +33,9 @@ on:
jobs:
ios-beta:
name: Apple TestFlight
runs-on: macos-12
runs-on: macos-13
env:
DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer
LANG: en_US.UTF-8 # Fastlane complains that the terminal is using ASCII.
LANGUAGE: en_US.UTF-8
LC_ALL: en_US.UTF-8
@ -39,7 +45,7 @@ jobs:
shell: bash
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 100 # enough to get all commits for the current day
@ -47,7 +53,7 @@ jobs:
run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20))
- name: Checkout private keys
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.PRIVATE_REPO }}
ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
@ -60,7 +66,16 @@ jobs:
rm -rf ./private.git
- name: Compile and upload to TestFlight
run: ./fastlane.sh upload_testflight
run: |
echo "IOS_VERSION=$(tools/unix/version.sh ios_version)-$(tools/unix/version.sh ios_build)" >> "$GITHUB_ENV"
./fastlane.sh upload_testflight
env:
APPSTORE_CERTIFICATE_PASSWORD: '${{ secrets.APPSTORE_CERTIFICATE_PASSWORD }}'
working-directory: xcode
- name: Upload ipa and DSYMs artifacts
uses: actions/upload-artifact@v4
with:
name: ipa and DSYM archive ${{ env.IOS_VERSION }}
path: xcode/build/*
if-no-files-found: error

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Check metadata
run: ./tools/python/check_store_metadata.py ios

View file

@ -1,6 +1,9 @@
name: iOS Check
on:
workflow_dispatch: # Manual trigger
push:
branches:
- master
pull_request:
paths-ignore:
- .gitignore
@ -18,6 +21,11 @@ on:
- generator/**
- iphone/metadata/**
- packaging/**
- platform/*_android*
- platform/*_linux*
- platform/*_mac*
- platform/*qt*
- platform/*_win*
- pyhelpers/**
- qt*/**
- skin_generator/**
@ -27,8 +35,9 @@ on:
jobs:
ios-check:
name: Build iOS
runs-on: macos-12
runs-on: macos-13
env:
DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer
LANG: en_US.UTF-8 # Fastlane complains that the terminal is using ASCII.
LANGUAGE: en_US.UTF-8
LC_ALL: en_US.UTF-8
@ -36,9 +45,14 @@ jobs:
fail-fast: false
matrix:
buildType: [Debug, Release]
# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
group: ${{ github.workflow }}-${{ matrix.buildType }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Parallel submodules checkout
shell: bash
@ -48,11 +62,17 @@ jobs:
shell: bash
run: ./configure.sh
- name: Configure ccache
uses: mikehardy/buildcache-action@v2.1.0
with:
cache_key: ${{ github.workflow }}-${{ matrix.buildType }}
- name: Compile
shell: bash
# Check for compilation errors.
run: |
xcodebuild \
CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \
-workspace xcode/omim.xcworkspace \
-scheme OMaps \
-configuration ${{ matrix.buildType }} build \

View file

@ -5,18 +5,19 @@ on:
jobs:
ios-release:
name: iOS Release
runs-on: macos-12
runs-on: macos-13
env:
DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer
LANG: en_US.UTF-8 # Fastlane complains that the terminal is using ASCII.
LANGUAGE: en_US.UTF-8
LC_ALL: en_US.UTF-8
environment: production
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Checkout private keys
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.PRIVATE_REPO }}
ssh-key: ${{ secrets.PRIVATE_SSH_KEY }}
@ -31,7 +32,7 @@ jobs:
rm -rf ./private.git
- name: Checkout screenshots
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.SCREENSHOTS_REPO }}
ssh-key: ${{ secrets.SCREENSHOTS_SSH_KEY }}
@ -39,7 +40,7 @@ jobs:
path: screenshots
- name: Checkout keywords
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: ${{ secrets.KEYWORDS_REPO }}
ssh-key: ${{ secrets.KEYWORDS_SSH_KEY }}

View file

@ -1,6 +1,9 @@
name: Linux Check
on:
workflow_dispatch: # Manual trigger
push:
branches:
- master
pull_request:
paths-ignore:
- .gitignore
@ -15,19 +18,25 @@ on:
- data/strings/**
- docs/**
- packaging/**
- platform/*apple*
- platform/*_android*
- platform/*_ios*
- platform/*_mac*
- platform/*_win*
- pyhelpers/**
- tools/**
- '!tools/python/run_desktop_tests.py'
- '!tools/python/testserver.py'
- '!tools/python/SiblingKiller.py'
- '!tools/python/test_server/**'
- xcode/**
jobs:
linux-no-unity:
name: Linux no unity build
runs-on: ubuntu-22.04
strategy:
fail-fast: false
# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
group: ${{ github.workflow }}-no-unity-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Free disk space by removing .NET, Android and Haskell
shell: bash
@ -35,7 +44,7 @@ jobs:
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 100 # enough to get all commits for the current day
@ -49,21 +58,34 @@ jobs:
sudo apt update -y
sudo apt install -y \
ninja-build \
qtbase5-dev \
libqt5svg5-dev
libgl1-mesa-dev \
libglvnd-dev \
qt6-base-dev \
libqt6svg6-dev \
qt6-positioning-dev \
libqt6positioning6-plugins \
libqt6positioning6
- name: Configure
shell: bash
run: ./configure.sh
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.workflow }}-no-unity
- name: CMake
shell: bash
env:
CC: clang-14
CXX: clang++-14
CMAKE_C_COMPILER_LAUNCHER: ccache
CMAKE_CXX_COMPILER_LAUNCHER: ccache
# -g1 should slightly reduce build time.
run: |
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-g1 -DUNITY_DISABLE=ON
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS=-g1 -DUNITY_DISABLE=ON
- name: Compile
shell: bash
@ -78,6 +100,10 @@ jobs:
matrix:
compiler: [{ CXX: g++-12, CC: gcc-12 }, { CXX: clang++-14, CC: clang-14 }]
CMAKE_BUILD_TYPE: [Debug, RelWithDebInfo]
# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
group: ${{ github.workflow }}-unity-${{ matrix.compiler.CC }}-${{ matrix.CMAKE_BUILD_TYPE }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Free disk space by removing .NET, Android and Haskell
@ -86,7 +112,7 @@ jobs:
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Parallel submodules checkout
shell: bash
@ -100,58 +126,61 @@ jobs:
g++-12 \
gcc-12 \
ninja-build \
qtbase5-dev \
libqt5svg5-dev
libgl1-mesa-dev \
libglvnd-dev \
qt6-base-dev \
libqt6svg6-dev \
qt6-positioning-dev \
libqt6positioning6-plugins \
libqt6positioning6
- name: Configure
shell: bash
run: ./configure.sh
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.workflow }}-unity-${{ matrix.compiler.CC }}-${{ matrix.CMAKE_BUILD_TYPE }}
- name: CMake
shell: bash
env:
CC: ${{ matrix.compiler.CC }}
CXX: ${{ matrix.compiler.CXX }}
CMAKE_C_COMPILER_LAUNCHER: ccache
CMAKE_CXX_COMPILER_LAUNCHER: ccache
# -g1 should slightly reduce build time.
run: |
echo "Building ${{ matrix.CMAKE_BUILD_TYPE }}"
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.CMAKE_BUILD_TYPE }} -DCMAKE_C_FLAGS=-g1 -DCMAKE_CXX_FLAGS=-g1
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.CMAKE_BUILD_TYPE }} \
-DCMAKE_C_FLAGS=-g1 -DCMAKE_CXX_FLAGS=-g1
- name: Compile
shell: bash
working-directory: build
run: ninja
- name: Checkout world_feed_integration_tests_data
uses: actions/checkout@v3
with:
repository: organicmaps/world_feed_integration_tests_data
path: data/world_feed_integration_tests_data
- name: Tests
shell: bash
# generator_integration_tests - https://github.com/organicmaps/organicmaps/issues/225
# routing_integration_tests - https://github.com/organicmaps/organicmaps/issues/221
# routing_quality_tests - https://github.com/organicmaps/organicmaps/issues/215
# drape_tests - requires X Window
# Separate run of OH boost-based test
working-directory: build
env:
# drape_tests - requires X Window
# generator_integration_tests - https://github.com/organicmaps/organicmaps/issues/225
# opening_hours_integration_tests - https://github.com/organicmaps/organicmaps/issues/219
# opening_hours_supported_features_tests - https://github.com/organicmaps/organicmaps/issues/219
# routing_integration_tests - https://github.com/organicmaps/organicmaps/issues/221
# shaders_tests - https://github.com/organicmaps/organicmaps/issues/223
# world_feed_integration_tests - https://github.com/organicmaps/organicmaps/issues/215
CTEST_EXCLUDE_REGEX: "drape_tests|generator_integration_tests|opening_hours_integration_tests|opening_hours_supported_features_tests|routing_benchmarks|routing_integration_tests|routing_quality_tests|search_quality_tests|storage_integration_tests|shaders_tests|world_feed_integration_tests"
run: |
./build/opening_hours_tests |
./tools/python/run_desktop_tests.py \
-f ./build \
-u ./data \
-d ./data \
-e generator_integration_tests \
-e routing_integration_tests \
-e routing_quality_tests \
-e search_quality_tests \
-e world_feed_integration_tests \
-e drape_tests \
-e shaders_tests \
\
-e opening_hours_tests \
-e opening_hours_integration_tests \
-e routing_consistency_tests \
-e opening_hours_supported_features_tests \
-e storage_integration_tests \
sudo locale-gen en_US
sudo locale-gen en_US.UTF-8
sudo locale-gen es_ES
sudo locale-gen es_ES.UTF-8
sudo locale-gen fr_FR
sudo locale-gen fr_FR.UTF-8
sudo locale-gen ru_RU
sudo locale-gen ru_RU.UTF-8
sudo update-locale
ctest -L "omim-test" -E "$CTEST_EXCLUDE_REGEX" --output-on-failure

View file

@ -1,6 +1,9 @@
name: macOS Check
on:
workflow_dispatch: # Manual trigger
push:
branches:
- master
pull_request:
paths-ignore:
- .gitignore
@ -15,28 +18,35 @@ on:
- data/strings/**
- docs/**
- packaging/**
- platform/*_android*
- platform/*_ios*
- platform/*_linux*
- platform/*_win*
- pyhelpers/**
- tools/**
- '!tools/python/run_desktop_tests.py'
- '!tools/python/testserver.py'
- '!tools/python/SiblingKiller.py'
- '!tools/python/test_server/**'
- xcode/**
jobs:
macos-matrix:
name: macOS builds and tests
runs-on: macos-12
runs-on: macos-13
env:
DEVELOPER_DIR: /Applications/Xcode_15.0.1.app/Contents/Developer
HOMEBREW_NO_ANALYTICS: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
strategy:
fail-fast: false
matrix:
CMAKE_BUILD_TYPE: [Debug, RelWithDebInfo]
# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
group: ${{ github.workflow }}-${{ matrix.CMAKE_BUILD_TYPE }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Checkout sources
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Parallel submodules checkout
shell: bash
@ -45,53 +55,43 @@ jobs:
- name: Install build tools and dependencies
shell: bash
run: |
brew install ninja qt@5
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install ninja qt@6
- name: Configure
shell: bash
run: ./configure.sh
- name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ github.workflow }}-${{ matrix.CMAKE_BUILD_TYPE }}
- name: CMake
shell: bash
env:
CMAKE_C_COMPILER_LAUNCHER: ccache
CMAKE_CXX_COMPILER_LAUNCHER: ccache
run: |
echo "Building ${{ matrix.CMAKE_BUILD_TYPE }}"
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.CMAKE_BUILD_TYPE }} -DCMAKE_C_FLAGS=-g1 -DCMAKE_CXX_FLAGS=-g1
cmake . -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.CMAKE_BUILD_TYPE }} \
-DCMAKE_C_FLAGS=-g1 -DCMAKE_CXX_FLAGS=-g1
- name: Compile
shell: bash
working-directory: build
run: ninja
- name: Checkout world_feed_integration_tests_data
uses: actions/checkout@v3
with:
repository: organicmaps/world_feed_integration_tests_data
path: data/world_feed_integration_tests_data
- name: Tests
shell: bash
# generator_integration_tests - https://github.com/organicmaps/organicmaps/issues/225
# # routing_integration_tests - https://github.com/organicmaps/organicmaps/issues/221
# routing_quality_tests - https://github.com/organicmaps/organicmaps/issues/215
# drape_tests - requires X Window
# Separate run of OH boost-based test
working-directory: build
env:
# drape_tests - requires X Window
# generator_integration_tests - https://github.com/organicmaps/organicmaps/issues/225
# opening_hours_integration_tests - https://github.com/organicmaps/organicmaps/issues/219
# opening_hours_supported_features_tests - https://github.com/organicmaps/organicmaps/issues/219
# routing_integration_tests - https://github.com/organicmaps/organicmaps/issues/221
# shaders_tests - https://github.com/organicmaps/organicmaps/issues/223
# world_feed_integration_tests - https://github.com/organicmaps/organicmaps/issues/215
CTEST_EXCLUDE_REGEX: "drape_tests|generator_integration_tests|opening_hours_integration_tests|opening_hours_supported_features_tests|routing_benchmarks|routing_integration_tests|routing_quality_tests|search_quality_tests|storage_integration_tests|shaders_tests|world_feed_integration_tests"
run: |
./build/opening_hours_tests |
./tools/python/run_desktop_tests.py \
-f ./build \
-u ./data \
-d ./data \
-e generator_integration_tests \
-e routing_integration_tests \
-e routing_quality_tests \
-e search_quality_tests \
-e world_feed_integration_tests \
-e drape_tests \
-e shaders_tests \
\
-e opening_hours_tests \
-e opening_hours_integration_tests \
-e routing_consistency_tests \
-e opening_hours_supported_features_tests \
-e storage_integration_tests
ctest -L "omim-test" -E "$CTEST_EXCLUDE_REGEX" --output-on-failure

View file

@ -14,8 +14,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v2
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3'

4
.gitignore vendored
View file

@ -84,6 +84,7 @@ data/[0-9][0-9][0-9][0-9][0-9][0-9]
data/gps_track.dat
# temporary files for downloader
data/settings.ini
data/world_feed_integration_tests_data
# benchmark results
data/benchmarks/*.trace
@ -127,6 +128,7 @@ tizen/*/crash-info/*
.private_repository_url
.private_repository_branch
private.h
# ignore old android secrets during the transition period to the new project structure
android/release.keystore
android/secure.properties
android/libnotify.properties
@ -136,7 +138,7 @@ android/firebase-app-distribution.json
android/firebase-test-lab.json
android/huawei-appgallery.json
android/res/xml/network_security_config.xml
server
./server/
iphone/Maps/app.omaps/
*.li

11
.gitmodules vendored
View file

@ -37,7 +37,7 @@
url = https://github.com/unicode-org/icu.git
[submodule "3party/freetype/freetype"]
path = 3party/freetype/freetype
url = https://github.com/freetype/freetype.git
url = https://github.com/organicmaps/freetype.git
[submodule "3party/googletest"]
path = 3party/googletest
url = https://github.com/google/googletest.git
@ -53,3 +53,12 @@
[submodule "3party/gflags"]
path = 3party/gflags
url = https://github.com/gflags/gflags
[submodule "3party/fast_obj"]
path = 3party/fast_obj
url = https://github.com/thisistherk/fast_obj
[submodule "3party/harfbuzz/harfbuzz"]
path = 3party/harfbuzz/harfbuzz
url = https://github.com/harfbuzz/harfbuzz.git
[submodule "3party/utfcpp"]
path = 3party/utfcpp
url = https://github.com/nemtrif/utfcpp.git

63
3party/CMakeLists.txt Normal file
View file

@ -0,0 +1,63 @@
# Fixes CMake deprecation warning:
# Compatibility with CMake < 3.5 will be removed from a future version of CMake.
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE)
if (WITH_SYSTEM_PROVIDED_3PARTY)
set(GFLAGS_USE_TARGET_NAMESPACE ON)
find_package(gflags REQUIRED GLOBAL)
else()
# Configure expat library.
# Suppress "Policy CMP0077 is not set: option() honors normal variables"
# for the expat options below.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(EXPAT_BUILD_TOOLS OFF)
set(EXPAT_BUILD_EXAMPLES OFF)
set(EXPAT_BUILD_TESTS OFF)
set(EXPAT_BUILD_DOCS OFF)
set(EXPAT_BUILD_PKGCONFIG OFF)
set(EXPAT_ENABLE_INSTALL OFF)
set(EXPAT_SHARED_LIBS OFF)
add_subdirectory(expat/expat)
# Configure Jansson library.
set(JANSSON_BUILD_DOCS OFF)
set(JANSSON_BUILD_MAN OFF)
set(JANSSON_EXAMPLES OFF)
set(JANSSON_INSTALL OFF)
set(JANSSON_WITHOUT_TESTS ON)
add_subdirectory(jansson/jansson/)
target_include_directories(jansson INTERFACE "${PROJECT_BINARY_DIR}/3party/jansson/jansson/include")
# Add gflags library.
add_subdirectory(gflags)
target_compile_options(gflags_nothreads_static PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wno-subobject-linkage>)
# Add pugixml library.
add_subdirectory(pugixml)
# Add protobuf library.
add_subdirectory(protobuf)
endif()
add_subdirectory(agg)
add_subdirectory(bsdiff-courgette)
if (NOT LINUX_DETECTED)
add_subdirectory(freetype)
add_subdirectory(icu)
endif()
add_subdirectory(harfbuzz)
add_subdirectory(liboauthcpp)
add_subdirectory(minizip)
add_subdirectory(open-location-code)
add_subdirectory(opening_hours)
add_subdirectory(sdf_image)
add_subdirectory(stb_image)
add_subdirectory(succinct)
add_subdirectory(vulkan_wrapper)
if (PLATFORM_DESKTOP)
add_subdirectory(libtess2)
endif()

View file

@ -422,7 +422,7 @@ namespace agg
inline bool is_close(unsigned c)
{
return (c & ~(path_flags_cw | path_flags_ccw)) ==
(path_cmd_end_poly | path_flags_close);
(unsigned(path_cmd_end_poly) | path_flags_close);
}
//------------------------------------------------------------is_next_poly

View file

@ -68,7 +68,7 @@ namespace agg
*x = m_vertices[m_vertex];
*y = m_vertices[m_vertex + 1];
m_vertex += 2;
return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd;
}
// Supplemantary functions. num_vertices() actually returns doubled

View file

@ -429,7 +429,7 @@ namespace agg
static value_type luminance(const rgba& c)
{
// Calculate grayscale value as per ITU-R BT.709.
return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask));
return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * double(base_mask)));
}
static value_type luminance(const rgba16& c)
@ -530,13 +530,13 @@ namespace agg
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
return double(a) / double(base_mask);
}
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
return value_type(uround(a * double(base_mask)));
}
//--------------------------------------------------------------------
@ -674,7 +674,7 @@ namespace agg
else
{
calc_type v_ = (calc_type(v) * base_mask) / a;
v = value_type((v_ > base_mask) ? base_mask : v_);
v = value_type((v_ > base_mask) ? calc_type(base_mask) : v_);
}
}
return *this;
@ -684,7 +684,7 @@ namespace agg
self_type gradient(self_type c, double k) const
{
self_type ret;
calc_type ik = uround(k * base_scale);
calc_type ik = uround(k * double(base_scale));
ret.v = lerp(v, c.v, ik);
ret.a = lerp(a, c.a, ik);
return ret;
@ -921,7 +921,7 @@ namespace agg
//--------------------------------------------------------------------
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return value_type(a * b / cover_mask);
return value_type(a * value_type(b) / value_type(cover_mask));
}
//--------------------------------------------------------------------

View file

@ -323,13 +323,13 @@ namespace agg
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
return double(a) / double(base_mask);
}
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
return value_type(uround(a * double(base_mask)));
}
//--------------------------------------------------------------------
@ -701,13 +701,13 @@ namespace agg
//--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
return double(a) / double(base_mask);
}
//--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
return value_type(uround(a * double(base_mask)));
}
//--------------------------------------------------------------------
@ -888,7 +888,7 @@ namespace agg
AGG_INLINE self_type gradient(const self_type& c, double k) const
{
self_type ret;
calc_type ik = uround(k * base_mask);
calc_type ik = uround(k * double(base_mask));
ret.r = lerp(r, c.r, ik);
ret.g = lerp(g, c.g, ik);
ret.b = lerp(b, c.b, ik);
@ -1120,7 +1120,7 @@ namespace agg
//--------------------------------------------------------------------
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return value_type(a * b / cover_mask);
return value_type(a * double(b) / double(cover_mask));
}
//--------------------------------------------------------------------

View file

@ -98,6 +98,7 @@ namespace agg
m_markers.remove_all();
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
m_status = accumulate;
[[fallthrough]];
case accumulate:
if(is_stop(m_last_cmd)) return path_cmd_stop;
@ -137,6 +138,7 @@ namespace agg
}
m_generator.rewind(0);
m_status = generate;
[[fallthrough]];
case generate:
cmd = m_generator.vertex(x, y);

View file

@ -398,7 +398,7 @@ namespace agg
if(m_closed && !m_stop)
{
m_stop = true;
return path_cmd_end_poly | path_flags_close;
return unsigned(path_cmd_end_poly) | path_flags_close;
}
return path_cmd_stop;
}
@ -463,7 +463,7 @@ namespace agg
if(m_closed && !m_stop)
{
m_stop = true;
return path_cmd_end_poly | path_flags_close;
return unsigned(path_cmd_end_poly) | path_flags_close;
}
return path_cmd_stop;
}
@ -525,7 +525,7 @@ namespace agg
if(m_closed && !m_stop)
{
m_stop = true;
return path_cmd_end_poly | path_flags_close;
return unsigned(path_cmd_end_poly) | path_flags_close;
}
return path_cmd_stop;
}

View file

@ -54,7 +54,7 @@ namespace agg
if (cover < cover_full)
{
double x = double(cover) / cover_full;
double x = double(cover) / double(cover_full);
c.r *= x;
c.g *= x;
c.b *= x;

View file

@ -659,7 +659,7 @@ namespace agg
while(nb)
{
cell_ptr = *block_ptr++;
i = (nb > cell_block_size) ? cell_block_size : nb;
i = (nb > unsigned(cell_block_size)) ? unsigned(cell_block_size) : nb;
nb -= i;
while(i--)
{
@ -683,7 +683,7 @@ namespace agg
while(nb)
{
cell_ptr = *block_ptr++;
i = (nb > cell_block_size) ? cell_block_size : nb;
i = (nb > unsigned(cell_block_size)) ? unsigned(cell_block_size) : nb;
nb -= i;
while(i--)
{

View file

@ -35,7 +35,7 @@ namespace agg
}
static int xi(int v) { return v; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
static int upscale(double v) { return iround(v * double(poly_subpixel_scale)); }
static int downscale(int v) { return v; }
};
@ -51,7 +51,7 @@ namespace agg
static int yi(int v) { return v; }
static int upscale(double v)
{
return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
return saturation<poly_max_coord>::iround(v * double(poly_subpixel_scale));
}
static int downscale(int v) { return v; }
};
@ -66,7 +66,7 @@ namespace agg
}
static int xi(int v) { return v * 3; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
static int upscale(double v) { return iround(v * double(poly_subpixel_scale)); }
static int downscale(int v) { return v; }
};
@ -78,8 +78,8 @@ namespace agg
{
return a * b / c;
}
static int xi(double v) { return iround(v * poly_subpixel_scale); }
static int yi(double v) { return iround(v * poly_subpixel_scale); }
static int xi(double v) { return iround(v * double(poly_subpixel_scale)); }
static int yi(double v) { return iround(v * double(poly_subpixel_scale)); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / double(poly_subpixel_scale); }
};
@ -92,8 +92,8 @@ namespace agg
{
return a * b / c;
}
static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
static int yi(double v) { return iround(v * poly_subpixel_scale); }
static int xi(double v) { return iround(v * double(poly_subpixel_scale) * 3); }
static int yi(double v) { return iround(v * double(poly_subpixel_scale)); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / double(poly_subpixel_scale); }
};

View file

@ -196,11 +196,11 @@ namespace agg
case end_poly1:
m_status = m_prev_status;
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
return unsigned(path_cmd_end_poly) | path_flags_close | path_flags_ccw;
case end_poly2:
m_status = m_prev_status;
return path_cmd_end_poly | path_flags_close | path_flags_cw;
return unsigned(path_cmd_end_poly) | path_flags_close | path_flags_cw;
case stop:
cmd = path_cmd_stop;

@ -1 +1 @@
Subproject commit 5002c2d6a2b5ed56a82128797828de95dab2ddba
Subproject commit 564e2ac16907019696cdaba8a93e3588ec596062

1
3party/fast_obj Submodule

@ -0,0 +1 @@
Subproject commit 1a8060257a96401a9555a476bd13c3a87502c9b5

View file

@ -1,7 +1,11 @@
# TODO: Check if enabling it provides benefits.
set(FT_DISABLE_HARFBUZZ ON)
add_subdirectory(freetype)
# Fix warning with ONE_PIXEL macro clash.
target_compile_options(freetype PRIVATE -Wno-macro-redefined)
# Use ft2build.h from the current directory instead of the default.
target_include_directories(freetype
BEFORE PUBLIC
@ -10,3 +14,4 @@ target_include_directories(freetype
)
add_library(Freetype::Freetype ALIAS freetype)

@ -1 +1 @@
Subproject commit 4eb6cb8818057a022f97176b53738ee3098c8eb6
Subproject commit e4586d960f339cf75e2e0b34aee30a0ed8353c0d

View file

@ -0,0 +1,38 @@
project(harfbuzz)
set(SOURCES
harfbuzz/src/harfbuzz.cc
)
add_library(${PROJECT_NAME} ${SOURCES})
target_include_directories(${PROJECT_NAME}
PUBLIC
harfbuzz/src
)
# Keep these settigns in sync with xcode/harfbuzz project.
target_compile_options(${PROJECT_NAME}
PRIVATE
-fno-rtti
-fno-exceptions
-fno-threadsafe-statics
)
target_compile_definitions(${PROJECT_NAME}
PRIVATE
HAVE_FREETYPE=1
# TODO: Enable later if necessary, and sync with xcode/harfbuzz project.
#HAVE_ICU
#$<$<BOOL:${APPLE}>:HAVE_CORETEXT>
HAVE_ATEXIT
HAVE_GETPAGESIZE
HAVE_MMAP
HAVE_MPROTECT
HAVE_PTHREAD
HAVE_SYSCONF
HAVE_SYS_MMAN_H
HAVE_UNISTD_H
)
target_link_libraries(${PROJECT_NAME} Freetype::Freetype)

@ -0,0 +1 @@
Subproject commit e8eb1dc5ff695427abc137d3d15c4eec64ab6c78

@ -1 +1 @@
Subproject commit 904cf62457de2440e8526deb75c95a3f7296f517
Subproject commit 680f521746a3bd6a86f25f25ee50a62d88b489cf

View file

@ -221,8 +221,7 @@ static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
return ret;
}
void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def;
void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def)
{
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;

View file

@ -21,8 +21,6 @@ omim_add_library(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} INTERFACE .)
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated-copy)
omim_add_test_subdirectory(opening_hours_tests)
omim_add_test_subdirectory(opening_hours_integration_tests)
omim_add_test_subdirectory(opening_hours_supported_features_tests)

View file

@ -387,7 +387,7 @@ bool operator==(Timespan const & lhs, Timespan const & rhs)
return lhs.GetStart() == rhs.GetStart() &&
lhs.GetEnd() == rhs.GetEnd() &&
lhs.GetPeriod() == lhs.GetPeriod();
lhs.GetPeriod() == rhs.GetPeriod();
}
// NthWeekdayOfTheMonthEntry -----------------------------------------------------------------------

View file

@ -2,14 +2,9 @@ project(opening_hours_integration_tests)
set(SRC opening_hours_integration_tests.cpp)
omim_add_executable(${PROJECT_NAME} ${SRC})
omim_add_test(${PROJECT_NAME} ${SRC} BOOST_TEST)
target_link_libraries(${PROJECT_NAME} opening_hours)
# Silence boost::test warnings.
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-but-set-variable>
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(COPY_CMD cp -u)

View file

@ -2,11 +2,6 @@ project(opening_hours_supported_features_tests)
set(SRC opening_hours_supported_features_tests.cpp)
omim_add_executable(${PROJECT_NAME} ${SRC})
omim_add_test(${PROJECT_NAME} ${SRC} BOOST_TEST)
target_link_libraries(${PROJECT_NAME} opening_hours)
# Silence boost::test warnings.
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-but-set-variable>
)

View file

@ -2,11 +2,6 @@ project(opening_hours_tests)
set(SRC opening_hours_tests.cpp)
omim_add_executable(${PROJECT_NAME} ${SRC})
omim_add_test(${PROJECT_NAME} ${SRC} BOOST_TEST)
target_link_libraries(${PROJECT_NAME} opening_hours)
# Silence boost::test warnings.
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-but-set-variable>
)

View file

@ -31,17 +31,17 @@ namespace osmoh
date_offset = ((lit('+')[_a = true] | lit('-')[_a = false])
>> charset::no_case[wdays] >> day_offset)
[bind(&DateOffset::SetWDayOffset, _val, _1),
bind(&DateOffset::SetOffset, _val, _2),
bind(&DateOffset::SetWDayOffsetPositive, _val, _a)]
[(bind(&DateOffset::SetWDayOffset, _val, _1),
bind(&DateOffset::SetOffset, _val, _2),
bind(&DateOffset::SetWDayOffsetPositive, _val, _a))]
| ((lit('+')[_a = true] | lit('-') [_a = false]) >> charset::no_case[wdays])
[bind(&DateOffset::SetWDayOffset, _val, _1),
bind(&DateOffset::SetWDayOffsetPositive, _val, _a)]
[(bind(&DateOffset::SetWDayOffset, _val, _1),
bind(&DateOffset::SetWDayOffsetPositive, _val, _a))]
| day_offset [bind(&DateOffset::SetOffset, _val, _1)]
;
date_left = (year >> charset::no_case[month]) [bind(&MonthDay::SetYear, _val, _1),
bind(&MonthDay::SetMonth, _val, _2)]
date_left = (year >> charset::no_case[month]) [(bind(&MonthDay::SetYear, _val, _1),
bind(&MonthDay::SetMonth, _val, _2))]
| charset::no_case[month] [bind(&MonthDay::SetMonth, _val, _1)]
;
@ -50,10 +50,10 @@ namespace osmoh
;
date_from = (date_left >> (daynum >> !(lit(':') >> qi::digit)))
[_val = _1, bind(&MonthDay::SetDayNum, _val, _2)]
| (year >> charset::no_case[lit("easter")]) [bind(&MonthDay::SetYear, _val, _1),
bind(&MonthDay::SetVariableDate, _val,
MonthDay::VariableDate::Easter)]
[(_val = _1, bind(&MonthDay::SetDayNum, _val, _2))]
| (year >> charset::no_case[lit("easter")]) [(bind(&MonthDay::SetYear, _val, _1),
bind(&MonthDay::SetVariableDate, _val,
MonthDay::VariableDate::Easter))]
| charset::no_case[lit("easter")] [bind(&MonthDay::SetVariableDate, _val,
MonthDay::VariableDate::Easter)]
;
@ -63,26 +63,26 @@ namespace osmoh
;
date_from_with_offset = (date_from >> date_offset)
[_val = _1, bind(&MonthDay::SetOffset, _val, _2)]
[(_val = _1, bind(&MonthDay::SetOffset, _val, _2))]
| date_from [_val = _1]
;
date_to_with_offset = (date_to >> date_offset)
[_val = _1, bind(&MonthDay::SetOffset, _val, _2)]
[(_val = _1, bind(&MonthDay::SetOffset, _val, _2))]
| date_to [_val = _1]
;
monthday_range = (date_from_with_offset >> dash >> date_to_with_offset)
[bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetEnd, _val, _2)]
| (date_from_with_offset >> '+') [bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetPlus, _val, true)]
[(bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetEnd, _val, _2))]
| (date_from_with_offset >> '+') [(bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetPlus, _val, true))]
| (date_left >> dash >> date_right >> '/' >> uint_)
[bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetEnd, _val, _2),
bind(&MonthdayRange::SetPeriod, _val, _3)]
| (date_left >> lit("-") >> date_right) [bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetEnd, _val, _2)]
[(bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetEnd, _val, _2),
bind(&MonthdayRange::SetPeriod, _val, _3))]
| (date_left >> lit("-") >> date_right) [(bind(&MonthdayRange::SetStart, _val, _1),
bind(&MonthdayRange::SetEnd, _val, _2))]
| date_from [bind(&MonthdayRange::SetStart, _val, _1)]
| date_left [bind(&MonthdayRange::SetStart, _val, _1)]
;

View file

@ -90,8 +90,8 @@ namespace parsing
[bind(&RuleSequence::SetModifier, _r1, Modifier::Unknown)] >>
-(comment [bind(&RuleSequence::SetModifierComment, _r1, _1)]))
| comment [bind(&RuleSequence::SetModifier, _r1, Modifier::Comment),
bind(&RuleSequence::SetModifierComment, _r1, _1)]
| comment [(bind(&RuleSequence::SetModifier, _r1, Modifier::Comment),
bind(&RuleSequence::SetModifierComment, _r1, _1))]
;
rule_sequence =

View file

@ -24,13 +24,13 @@ namespace osmoh
using osmoh::Timespan;
hour_minutes =
(hours >> lit(':') >> minutes) [bind(&HourMinutes::AddDuration, _val, _1),
bind(&HourMinutes::AddDuration, _val, _2)]
(hours >> lit(':') >> minutes) [(bind(&HourMinutes::AddDuration, _val, _1),
bind(&HourMinutes::AddDuration, _val, _2))]
;
extended_hour_minutes =
(exthours >> lit(':') >> minutes)[bind(&HourMinutes::AddDuration, _val, _1),
bind(&HourMinutes::AddDuration, _val, _2)]
(exthours >> lit(':') >> minutes)[(bind(&HourMinutes::AddDuration, _val, _1),
bind(&HourMinutes::AddDuration, _val, _2))]
;
variable_time =
@ -53,27 +53,27 @@ namespace osmoh
timespan =
(time >> dash >> extended_time >> '/' >> hour_minutes)
[bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2),
bind(&Timespan::SetPeriod, _val, _3)]
[(bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2),
bind(&Timespan::SetPeriod, _val, _3))]
| (time >> dash >> extended_time >> '/' >> minutes)
[bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2),
bind(&Timespan::SetPeriod, _val, _3)]
[(bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2),
bind(&Timespan::SetPeriod, _val, _3))]
| (time >> dash >> extended_time >> '+')
[bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2),
bind(&Timespan::SetPlus, _val, true)]
[(bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2),
bind(&Timespan::SetPlus, _val, true))]
| (time >> dash >> extended_time)
[bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2)]
[(bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetEnd, _val, _2))]
| (time >> '+')
[bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetPlus, _val, true)]
[(bind(&Timespan::SetStart, _val, _1),
bind(&Timespan::SetPlus, _val, true))]
// This rule is only used for collection_times tag wish is not in our interest.
// | time[bind(&Timespan::SetStart, _val, _1)]

View file

@ -27,8 +27,8 @@ namespace osmoh
| ushort_(4) [_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::Fourth]
| ushort_(5) [_val = NthWeekdayOfTheMonthEntry::NthDayOfTheMonth::Fifth];
nth_entry = (nth >> dash >> nth) [bind(&NthWeekdayOfTheMonthEntry::SetStart, _val, _1),
bind(&NthWeekdayOfTheMonthEntry::SetEnd, _val, _2)]
nth_entry = (nth >> dash >> nth) [(bind(&NthWeekdayOfTheMonthEntry::SetStart, _val, _1),
bind(&NthWeekdayOfTheMonthEntry::SetEnd, _val, _2))]
| (lit('-') >> nth) [bind(&NthWeekdayOfTheMonthEntry::SetEnd, _val, _1)]
| nth [bind(&NthWeekdayOfTheMonthEntry::SetStart, _val, _1)]
;
@ -50,8 +50,8 @@ namespace osmoh
( charset::no_case[wdays] [bind(&WeekdayRange::SetStart, _val, _1)] >>
'[' >> (nth_entry [bind(&WeekdayRange::AddNth, _val, _1)]) % ',') >> ']' >>
-(day_offset [bind(&WeekdayRange::SetOffset, _val, _1)])
| charset::no_case[(wdays >> dash >> wdays)] [bind(&WeekdayRange::SetStart, _val, _1),
bind(&WeekdayRange::SetEnd, _val, _2)]
| charset::no_case[(wdays >> dash >> wdays)] [(bind(&WeekdayRange::SetStart, _val, _1),
bind(&WeekdayRange::SetEnd, _val, _2))]
| charset::no_case[wdays] [bind(&WeekdayRange::SetStart, _val, _1)]
;
@ -59,8 +59,8 @@ namespace osmoh
;
main = (holiday_sequence >> -lit(',') >> weekday_sequence)
[bind(&Weekdays::SetHolidays, _val, _1),
bind(&Weekdays::SetWeekdayRanges, _val, _2)]
[(bind(&Weekdays::SetHolidays, _val, _1),
bind(&Weekdays::SetWeekdayRanges, _val, _2))]
| holiday_sequence [bind(&Weekdays::SetHolidays, _val, _1)]
| weekday_sequence [bind(&Weekdays::SetWeekdayRanges, _val, _1)]
;

View file

@ -18,11 +18,11 @@ namespace osmoh
using qi::_val;
using osmoh::WeekRange;
week = (weeknum >> dash >> weeknum >> '/' >> uint_) [bind(&WeekRange::SetStart, _val, _1),
bind(&WeekRange::SetEnd, _val, _2),
bind(&WeekRange::SetPeriod, _val, _3)]
| (weeknum >> dash >> weeknum) [bind(&WeekRange::SetStart, _val, _1),
bind(&WeekRange::SetEnd, _val, _2)]
week = (weeknum >> dash >> weeknum >> '/' >> uint_) [(bind(&WeekRange::SetStart, _val, _1),
bind(&WeekRange::SetEnd, _val, _2),
bind(&WeekRange::SetPeriod, _val, _3))]
| (weeknum >> dash >> weeknum) [(bind(&WeekRange::SetStart, _val, _1),
bind(&WeekRange::SetEnd, _val, _2))]
| weeknum [bind(&WeekRange::SetStart, _val, _1)]
;

View file

@ -20,13 +20,13 @@ namespace osmoh
static const qi::int_parser<unsigned, 10, 4, 4> year = {};
year_range = (year >> dash >> year >> '/' >> uint_) [bind(&YearRange::SetStart, _val, _1),
bind(&YearRange::SetEnd, _val, _2),
bind(&YearRange::SetPeriod, _val, _3)]
| (year >> dash >> year) [bind(&YearRange::SetStart, _val, _1),
bind(&YearRange::SetEnd, _val, _2)]
| (year >> lit('+')) [bind(&YearRange::SetStart, _val, _1),
bind(&YearRange::SetPlus, _val, true)]
year_range = (year >> dash >> year >> '/' >> uint_) [(bind(&YearRange::SetStart, _val, _1),
bind(&YearRange::SetEnd, _val, _2),
bind(&YearRange::SetPeriod, _val, _3))]
| (year >> dash >> year) [(bind(&YearRange::SetStart, _val, _1),
bind(&YearRange::SetEnd, _val, _2))]
| (year >> lit('+')) [(bind(&YearRange::SetStart, _val, _1),
bind(&YearRange::SetPlus, _val, true))]
;
main %= (year_range % ',');

View file

@ -0,0 +1 @@
../../utfcpp/source

1
3party/utfcpp Submodule

@ -0,0 +1 @@
Subproject commit 6f0e7c7865208f2a6b882a7e138584beb1b6b2fd

View file

@ -1,12 +0,0 @@
utf8 cpp library
Release 2.3.4
A minor bug fix release. Thanks to all who reported bugs.
Note: Version 2.3.3 contained a regression, and therefore was removed.
Changes from version 2.3.2
- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';'
- Bug fix [36]: replace_invalid() only works with back_inserter
Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes

File diff suppressed because it is too large Load diff

View file

@ -1,34 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "utf8/checked.h"
#include "utf8/unchecked.h"
#endif // header guard

View file

@ -1,335 +0,0 @@
// Copyright 2006-2016 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
#include <stdexcept>
namespace utf8
{
// Base for the exceptions that may be thrown from the library
class exception : public ::std::exception {
};
// Exceptions that may be thrown from the library functions.
class invalid_code_point : public exception {
uint32_t cp;
public:
invalid_code_point(uint32_t codepoint) : cp(codepoint) {}
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid code point"; }
uint32_t code_point() const {return cp;}
};
class invalid_utf8 : public exception {
uint8_t u8;
public:
invalid_utf8 (uint8_t u) : u8(u) {}
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-8"; }
uint8_t utf8_octet() const {return u8;}
};
class invalid_utf16 : public exception {
uint16_t u16;
public:
invalid_utf16 (uint16_t u) : u16(u) {}
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-16"; }
uint16_t utf16_word() const {return u16;}
};
class not_enough_room : public exception {
public:
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Not enough space"; }
};
/// The library API - functions intended to be called by the users
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (!utf8::internal::is_code_point_valid(cp))
throw invalid_code_point(cp);
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
template <typename octet_iterator, typename output_iterator>
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
{
while (start != end) {
octet_iterator sequence_start = start;
internal::utf_error err_code = utf8::internal::validate_next(start, end);
switch (err_code) {
case internal::UTF8_OK :
for (octet_iterator it = sequence_start; it != start; ++it)
*out++ = *it;
break;
case internal::NOT_ENOUGH_ROOM:
out = utf8::append (replacement, out);
start = end;
break;
case internal::INVALID_LEAD:
out = utf8::append (replacement, out);
++start;
break;
case internal::INCOMPLETE_SEQUENCE:
case internal::OVERLONG_SEQUENCE:
case internal::INVALID_CODE_POINT:
out = utf8::append (replacement, out);
++start;
// just one replacement mark for the sequence
while (start != end && utf8::internal::is_trail(*start))
++start;
break;
}
}
return out;
}
template <typename octet_iterator, typename output_iterator>
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
{
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
return utf8::replace_invalid(start, end, out, replacement_marker);
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it, octet_iterator end)
{
uint32_t cp = 0;
internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
switch (err_code) {
case internal::UTF8_OK :
break;
case internal::NOT_ENOUGH_ROOM :
throw not_enough_room();
case internal::INVALID_LEAD :
case internal::INCOMPLETE_SEQUENCE :
case internal::OVERLONG_SEQUENCE :
throw invalid_utf8(*it);
case internal::INVALID_CODE_POINT :
throw invalid_code_point(cp);
}
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it, octet_iterator end)
{
return utf8::next(it, end);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it, octet_iterator start)
{
// can't do much if it == start
if (it == start)
throw not_enough_room();
octet_iterator end = it;
// Go back until we hit either a lead octet or start
while (utf8::internal::is_trail(*(--it)))
if (it == start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
return utf8::peek_next(it, end);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n, octet_iterator end)
{
const distance_type zero(0);
if (n < zero) {
// backward
for (distance_type i = n; i < zero; ++i)
utf8::prior(it, end);
} else {
// forward
for (distance_type i = zero; i < n; ++i)
utf8::next(it, end);
}
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
utf8::next(first, last);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = utf8::internal::mask16(*start++);
// Take care of surrogate pairs first
if (utf8::internal::is_lead_surrogate(cp)) {
if (start != end) {
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
if (utf8::internal::is_trail_surrogate(trail_surrogate))
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
else
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
}
else
throw invalid_utf16(static_cast<uint16_t>(cp));
}
// Lone trail surrogate
else if (utf8::internal::is_trail_surrogate(cp))
throw invalid_utf16(static_cast<uint16_t>(cp));
result = utf8::append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start < end) {
uint32_t cp = utf8::next(start, end);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = utf8::append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start < end)
(*result++) = utf8::next(start, end);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator {
octet_iterator it;
octet_iterator range_start;
octet_iterator range_end;
public:
typedef uint32_t value_type;
typedef uint32_t* pointer;
typedef uint32_t& reference;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
iterator () {}
explicit iterator (const octet_iterator& octet_it,
const octet_iterator& rangestart,
const octet_iterator& rangeend) :
it(octet_it), range_start(rangestart), range_end(rangeend)
{
if (it < range_start || it > range_end)
throw std::out_of_range("Invalid utf-8 iterator position");
}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return utf8::next(temp, range_end);
}
bool operator == (const iterator& rhs) const
{
if (range_start != rhs.range_start || range_end != rhs.range_end)
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
utf8::next(it, range_end);
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
utf8::next(it, range_end);
return temp;
}
iterator& operator -- ()
{
utf8::prior(it, range_start);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
utf8::prior(it, range_start);
return temp;
}
}; // class iterator
} // namespace utf8
#if UTF_CPP_CPLUSPLUS >= 201703L // C++ 17 or later
#include "cpp17.h"
#elif UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
#include "cpp11.h"
#endif // C++ 11 or later
#endif //header guard

View file

@ -1,338 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include <iterator>
// Determine the C++ standard version.
// If the user defines UTF_CPP_CPLUSPLUS, use that.
// Otherwise, trust the unreliable predefined macro __cplusplus
#if !defined UTF_CPP_CPLUSPLUS
#define UTF_CPP_CPLUSPLUS __cplusplus
#endif
#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
#define UTF_CPP_OVERRIDE override
#define UTF_CPP_NOEXCEPT noexcept
#else // C++ 98/03
#define UTF_CPP_OVERRIDE
#define UTF_CPP_NOEXCEPT throw()
#endif // C++ 11 or later
namespace utf8
{
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
// You may need to change them to match your system.
// These typedefs have the same names as ones from cstdint, or boost/cstdint
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Helper code - not intended to be directly called by the library users. May be changed at any time
namespace internal
{
// Unicode constants
// Leading (high) surrogates: 0xd800 - 0xdbff
// Trailing (low) surrogates: 0xdc00 - 0xdfff
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
const uint16_t LEAD_OFFSET = 0xd7c0u; // LEAD_SURROGATE_MIN - (0x10000 >> 10)
const uint32_t SURROGATE_OFFSET = 0xfca02400u; // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN
// Maximum valid value for a Unicode code point
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
template<typename octet_type>
inline uint8_t mask8(octet_type oc)
{
return static_cast<uint8_t>(0xff & oc);
}
template<typename u16_type>
inline uint16_t mask16(u16_type oc)
{
return static_cast<uint16_t>(0xffff & oc);
}
template<typename octet_type>
inline bool is_trail(octet_type oc)
{
return ((utf8::internal::mask8(oc) >> 6) == 0x2);
}
template <typename u16>
inline bool is_lead_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
}
template <typename u16>
inline bool is_trail_surrogate(u16 cp)
{
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u16>
inline bool is_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u32>
inline bool is_code_point_valid(u32 cp)
{
return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
}
template <typename octet_iterator>
inline typename std::iterator_traits<octet_iterator>::difference_type
sequence_length(octet_iterator lead_it)
{
uint8_t lead = utf8::internal::mask8(*lead_it);
if (lead < 0x80)
return 1;
else if ((lead >> 5) == 0x6)
return 2;
else if ((lead >> 4) == 0xe)
return 3;
else if ((lead >> 3) == 0x1e)
return 4;
else
return 0;
}
template <typename octet_difference_type>
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
{
if (cp < 0x80) {
if (length != 1)
return true;
}
else if (cp < 0x800) {
if (length != 2)
return true;
}
else if (cp < 0x10000) {
if (length != 3)
return true;
}
return false;
}
enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
/// Helper for get_sequence_x
template <typename octet_iterator>
utf_error increase_safely(octet_iterator& it, octet_iterator end)
{
if (++it == end)
return NOT_ENOUGH_ROOM;
if (!utf8::internal::is_trail(*it))
return INCOMPLETE_SEQUENCE;
return UTF8_OK;
}
#define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
/// get_sequence_x functions decode utf-8 sequences of the length x
template <typename octet_iterator>
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (*it) & 0x3f;
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (*it) & 0x3f;
return UTF8_OK;
}
#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
template <typename octet_iterator>
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
// Save the original value of it so we can go back in case of failure
// Of course, it does not make much sense with i.e. stream iterators
octet_iterator original_it = it;
uint32_t cp = 0;
// Determine the sequence length based on the lead octet
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
const octet_difference_type length = utf8::internal::sequence_length(it);
// Get trail octets and calculate the code point
utf_error err = UTF8_OK;
switch (length) {
case 0:
return INVALID_LEAD;
case 1:
err = utf8::internal::get_sequence_1(it, end, cp);
break;
case 2:
err = utf8::internal::get_sequence_2(it, end, cp);
break;
case 3:
err = utf8::internal::get_sequence_3(it, end, cp);
break;
case 4:
err = utf8::internal::get_sequence_4(it, end, cp);
break;
}
if (err == UTF8_OK) {
// Decoding succeeded. Now, security checks...
if (utf8::internal::is_code_point_valid(cp)) {
if (!utf8::internal::is_overlong_sequence(cp, length)){
// Passed! Return here.
code_point = cp;
++it;
return UTF8_OK;
}
else
err = OVERLONG_SEQUENCE;
}
else
err = INVALID_CODE_POINT;
}
// Failure branch - restore the original value of the iterator
it = original_it;
return err;
}
template <typename octet_iterator>
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
uint32_t ignored;
return utf8::internal::validate_next(it, end, ignored);
}
} // namespace internal
/// The library API - functions intended to be called by the users
// Byte order mark
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
template <typename octet_iterator>
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
{
octet_iterator result = start;
while (result != end) {
utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
if (err_code != internal::UTF8_OK)
return result;
}
return result;
}
template <typename octet_iterator>
inline bool is_valid(octet_iterator start, octet_iterator end)
{
return (utf8::find_invalid(start, end) == end);
}
template <typename octet_iterator>
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
{
return (
((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
((it != end) && (utf8::internal::mask8(*it)) == bom[2])
);
}
} // namespace utf8
#endif // header guard

View file

@ -1,103 +0,0 @@
// Copyright 2018 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
#define UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
#include "checked.h"
#include <string>
namespace utf8
{
inline void append(char32_t cp, std::string& s)
{
append(uint32_t(cp), std::back_inserter(s));
}
inline std::string utf16to8(const std::u16string& s)
{
std::string result;
utf16to8(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::u16string utf8to16(const std::string& s)
{
std::u16string result;
utf8to16(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::string utf32to8(const std::u32string& s)
{
std::string result;
utf32to8(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::u32string utf8to32(const std::string& s)
{
std::u32string result;
utf8to32(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::size_t find_invalid(const std::string& s)
{
std::string::const_iterator invalid = find_invalid(s.begin(), s.end());
return (invalid == s.end()) ? std::string::npos : (invalid - s.begin());
}
inline bool is_valid(const std::string& s)
{
return is_valid(s.begin(), s.end());
}
inline std::string replace_invalid(const std::string& s, char32_t replacement)
{
std::string result;
replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
return result;
}
inline std::string replace_invalid(const std::string& s)
{
std::string result;
replace_invalid(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline bool starts_with_bom(const std::string& s)
{
return starts_with_bom(s.begin(), s.end());
}
} // namespace utf8
#endif // header guard

View file

@ -1,103 +0,0 @@
// Copyright 2018 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
#define UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
#include "checked.h"
#include <string>
namespace utf8
{
inline void append(char32_t cp, std::string& s)
{
append(uint32_t(cp), std::back_inserter(s));
}
inline std::string utf16to8(std::u16string_view s)
{
std::string result;
utf16to8(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::u16string utf8to16(std::string_view s)
{
std::u16string result;
utf8to16(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::string utf32to8(std::u32string_view s)
{
std::string result;
utf32to8(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::u32string utf8to32(std::string_view s)
{
std::u32string result;
utf8to32(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline std::size_t find_invalid(std::string_view s)
{
std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end());
return (invalid == s.end()) ? std::string_view::npos : (invalid - s.begin());
}
inline bool is_valid(std::string_view s)
{
return is_valid(s.begin(), s.end());
}
inline std::string replace_invalid(std::string_view s, char32_t replacement)
{
std::string result;
replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
return result;
}
inline std::string replace_invalid(std::string_view s)
{
std::string result;
replace_invalid(s.begin(), s.end(), std::back_inserter(result));
return result;
}
inline bool starts_with_bom(std::string_view s)
{
return starts_with_bom(s.begin(), s.end());
}
} // namespace utf8
#endif // header guard

View file

@ -1,274 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
namespace utf8
{
namespace unchecked
{
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
template <typename octet_iterator, typename output_iterator>
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
{
while (start != end) {
octet_iterator sequence_start = start;
internal::utf_error err_code = utf8::internal::validate_next(start, end);
switch (err_code) {
case internal::UTF8_OK :
for (octet_iterator it = sequence_start; it != start; ++it)
*out++ = *it;
break;
case internal::NOT_ENOUGH_ROOM:
out = utf8::unchecked::append (replacement, out);
start = end;
break;
case internal::INVALID_LEAD:
out = utf8::unchecked::append (replacement, out);
++start;
break;
case internal::INCOMPLETE_SEQUENCE:
case internal::OVERLONG_SEQUENCE:
case internal::INVALID_CODE_POINT:
out = utf8::unchecked::append (replacement, out);
++start;
// just one replacement mark for the sequence
while (start != end && utf8::internal::is_trail(*start))
++start;
break;
}
}
return out;
}
template <typename octet_iterator, typename output_iterator>
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
{
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
return utf8::unchecked::replace_invalid(start, end, out, replacement_marker);
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it)
{
uint32_t cp = utf8::internal::mask8(*it);
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
switch (length) {
case 1:
break;
case 2:
it++;
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
break;
case 3:
++it;
cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
++it;
cp += (*it) & 0x3f;
break;
case 4:
++it;
cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
++it;
cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
++it;
cp += (*it) & 0x3f;
break;
}
++it;
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it)
{
return utf8::unchecked::next(it);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it)
{
while (utf8::internal::is_trail(*(--it))) ;
octet_iterator temp = it;
return utf8::unchecked::next(temp);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n)
{
const distance_type zero(0);
if (n < zero) {
// backward
for (distance_type i = n; i < zero; ++i)
utf8::unchecked::prior(it);
} else {
// forward
for (distance_type i = zero; i < n; ++i)
utf8::unchecked::next(it);
}
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
utf8::unchecked::next(first);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = utf8::internal::mask16(*start++);
// Take care of surrogate pairs first
if (utf8::internal::is_lead_surrogate(cp)) {
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
}
result = utf8::unchecked::append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start < end) {
uint32_t cp = utf8::unchecked::next(start);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = utf8::unchecked::append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start < end)
(*result++) = utf8::unchecked::next(start);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator {
octet_iterator it;
public:
typedef uint32_t value_type;
typedef uint32_t* pointer;
typedef uint32_t& reference;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
iterator () {}
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return utf8::unchecked::next(temp);
}
bool operator == (const iterator& rhs) const
{
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
::std::advance(it, utf8::internal::sequence_length(it));
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
::std::advance(it, utf8::internal::sequence_length(it));
return temp;
}
iterator& operator -- ()
{
utf8::unchecked::prior(it);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
utf8::unchecked::prior(it);
return temp;
}
}; // class iterator
} // namespace utf8::unchecked
} // namespace utf8
#endif // header guard

View file

@ -7,7 +7,16 @@ set(SRC
add_library(${PROJECT_NAME} ${SRC})
target_include_directories(${PROJECT_NAME} PUBLIC . ../Vulkan-Headers/include)
if (WITH_SYSTEM_PROVIDED_3PARTY)
find_package(VulkanHeaders REQUIRED)
target_link_libraries(${PROJECT_NAME} Vulkan::Headers)
else()
set(VulkanHeaders_INCLUDE_DIR ../Vulkan-Headers/include)
target_include_directories(${PROJECT_NAME} PUBLIC ../Vulkan-Headers/include)
endif()
target_include_directories(${PROJECT_NAME} PUBLIC .)
# dlopen
target_link_libraries(${PROJECT_NAME} $<$<BOOL:CMAKE_DL_LIBS>:${CMAKE_DL_LIBS}>)

View file

@ -961,8 +961,10 @@ PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
PFN_vkSetPrivateDataEXT vkSetPrivateDataEXT;
PFN_vkGetPrivateDataEXT vkGetPrivateDataEXT;
PFN_vkCmdSetFragmentShadingRateEnumNV vkCmdSetFragmentShadingRateEnumNV;
PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV;
PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV;
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkAcquireWinrtDisplayNV vkAcquireWinrtDisplayNV;
PFN_vkGetWinrtDisplayNV vkGetWinrtDisplayNV;
#endif
PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT;
PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI;
PFN_vkCmdSubpassShadingHUAWEI vkCmdSubpassShadingHUAWEI;

View file

@ -22,6 +22,8 @@ endif()
message(STATUS "Using compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
option(COVERAGE_REPORT "Configure for coverage report" OFF)
option(UNITY_DISABLE "Disable unity build" OFF)
if (NOT UNITY_DISABLE AND NOT DEFINED ENV{UNITY_DISABLE})
set(CMAKE_UNITY_BUILD ON)
@ -58,6 +60,7 @@ set(OMIM_ROOT ${CMAKE_SOURCE_DIR})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${OMIM_ROOT}/cmake")
include(OmimHelpers)
include(OmimTesting)
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(LINUX_DETECTED TRUE)
@ -131,7 +134,7 @@ option(USE_ASAN "Enable Address Sanitizer" OFF)
option(USE_TSAN "Enable Thread Sanitizer" OFF)
option(USE_LIBFUZZER "Enable LibFuzzer" OFF)
option(PYBINDINGS "Create makefiles for building python bindings" OFF)
option(SKIP_DESKTOP "Skip building of desktop application" OFF)
option(SKIP_QT_GUI "Skip building of Qt GUI" OFF)
# TODO: Fix mapshot, it doesn't work without our old FreeType hack.
option(BUILD_MAPSHOT "Build mapshot tool" OFF)
option(USE_PCH "Use precompiled headers" OFF)
@ -208,7 +211,12 @@ if (PLATFORM_LINUX OR PLATFORM_ANDROID)
endif()
if (NOT SKIP_TESTS)
set(SKIP_TESTS FALSE)
enable_testing()
# Enables ctest -T memcheck with valgrind
include(CTest)
if (COVERAGE_REPORT)
include(OmimCoverage)
endif ()
endif()
if (NOT PYTHON_VERSION)
@ -234,22 +242,14 @@ endif()
if (NOT PLATFORM_IPHONE AND NOT PLATFORM_ANDROID)
list(APPEND qt_components Core Network)
if (NOT SKIP_DESKTOP OR NOT SKIP_TESTS OR PYBINDINGS)
if (NOT SKIP_QT_GUI OR NOT SKIP_TESTS OR PYBINDINGS)
list(APPEND qt_components Widgets)
endif()
if (NOT SKIP_DESKTOP)
list(APPEND qt_components Gui Xml Svg)
endif()
if (DEFINED ENV{HOMEBREW_PREFIX})
set(HOMEBREW_PREFIX $ENV{HOMEBREW_PREFIX})
else()
set(HOMEBREW_PREFIX /opt/homebrew)
endif()
# PATHS are hard-coded hints where to look for qt5 in addition to other places.
find_package(Qt5 COMPONENTS REQUIRED ${qt_components} PATHS $ENV{QT_PATH} ${HOMEBREW_PREFIX}/opt/qt@5 /usr/local/opt/qt@5 /usr/lib/x86_64-linux-gnu/qt5)
if (Qt5_VERSION VERSION_LESS 5.5.0)
message(FATAL_ERROR "Minimum supported Qt5 version is 5.5")
if (NOT SKIP_QT_GUI)
list(APPEND qt_components Gui Xml Svg OpenGL OpenGLWidgets)
endif()
# PATHS are hard-coded hints where to look for qt6 in addition to other places.
find_package(Qt6 COMPONENTS REQUIRED ${qt_components} PATHS $ENV{QT_PATH} /opt/homebrew/opt/qt@6 /usr/local/opt/qt@6 /usr/lib/x86_64-linux-gnu/qt6)
endif()
find_library(LIBZ NAMES z)
@ -290,68 +290,21 @@ if (USE_PCH)
${OMIM_PCH_TARGET_NAME}
)
endif()
# Include 3party dependencies.
if (NOT WITH_SYSTEM_PROVIDED_3PARTY)
# Configure expat library.
# Suppress "Policy CMP0077 is not set: option() honors normal variables"
# for the expat options below.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(EXPAT_BUILD_TOOLS OFF)
set(EXPAT_BUILD_EXAMPLES OFF)
set(EXPAT_BUILD_TESTS OFF)
set(EXPAT_BUILD_DOCS OFF)
set(EXPAT_BUILD_PKGCONFIG OFF)
set(EXPAT_ENABLE_INSTALL OFF)
set(EXPAT_SHARED_LIBS OFF)
add_subdirectory(3party/expat/expat)
# Configure Jansson library.
set(JANSSON_BUILD_DOCS OFF)
set(JANSSON_BUILD_MAN OFF)
set(JANSSON_EXAMPLES OFF)
set(JANSSON_INSTALL OFF)
set(JANSSON_WITHOUT_TESTS ON)
add_subdirectory(3party/jansson/jansson/)
target_include_directories(jansson INTERFACE "${PROJECT_BINARY_DIR}/3party/jansson/jansson/include")
# Add pugixml library.
add_subdirectory(3party/pugixml)
# Add protobuf library.
add_subdirectory(${OMIM_ROOT}/3party/protobuf)
endif()
add_subdirectory(3party/agg)
add_subdirectory(3party/bsdiff-courgette)
add_subdirectory(3party/gflags)
target_compile_options(gflags_nothreads_static PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wno-subobject-linkage>)
# Not needed for the usual build process, but it fixes QtCreator editor,
# that doesn't see gflags/gflags.h in binary dir (gflags has tricky cmake configuration).
if (PLATFORM_DESKTOP)
include_directories("${PROJECT_BINARY_DIR}/3party/gflags/include")
endif()
# Should be on the root level, not in 3party, so tests can get these dependencies.
# Should go before 3party as harfbuzz is using them.
if (LINUX_DETECTED)
find_package(ICU COMPONENTS uc i18n data REQUIRED)
find_package(Freetype REQUIRED)
else()
add_subdirectory(3party/freetype)
add_subdirectory(3party/icu)
endif()
add_subdirectory(3party/liboauthcpp)
add_subdirectory(3party/minizip)
add_subdirectory(3party/opening_hours)
add_subdirectory(3party/sdf_image)
add_subdirectory(3party/stb_image)
add_subdirectory(3party/succinct)
add_subdirectory(3party/open-location-code)
add_subdirectory(3party/vulkan_wrapper)
# Include 3party dependencies.
add_subdirectory(3party)
if (PLATFORM_DESKTOP)
add_subdirectory(3party/libtess2)
# Not needed for the usual build process, but it fixes QtCreator editor,
# that doesn't see gflags/gflags.h in binary dir (gflags has tricky cmake configuration).
if (PLATFORM_DESKTOP AND NOT WITH_SYSTEM_PROVIDED_3PARTY)
include_directories("${PROJECT_BINARY_DIR}/3party/gflags/include")
endif()
find_package(Python3 COMPONENTS Interpreter)
@ -396,7 +349,7 @@ if (PLATFORM_DESKTOP)
omim_add_tool_subdirectory(topography_generator)
add_subdirectory(track_analyzing)
omim_add_tool_subdirectory(track_generator)
if (NOT SKIP_DESKTOP)
if (NOT SKIP_QT_GUI)
add_subdirectory(qt)
omim_add_tool_subdirectory(skin_generator)
endif()
@ -405,5 +358,5 @@ endif()
omim_add_test_subdirectory(qt_tstfrm)
if (PLATFORM_ANDROID)
add_subdirectory(android/jni)
add_subdirectory(android/app/src/main/cpp)
endif()

1
CONTRIBUTING.md Normal file
View file

@ -0,0 +1 @@
See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md)

View file

@ -38,6 +38,7 @@ Code contributions:
Roman Tsisyk <roman@tsisyk.com>
Caspar Nuël <casparnuel@yandex.com>
Konstantin Pastbin
Nishant Bhandari <nishantbhandari0019@gmail.com>
Porting to Tizen platform:
Sergey Pisarchik

1
INSTALL.md Normal file
View file

@ -0,0 +1 @@
See [docs/INSTALL.md](docs/INSTALL.md)

View file

@ -2,25 +2,25 @@
<a name="install"/>
[Organic Maps](https://organicmaps.app) is a free Android & iOS offline maps app for travelers, tourists, drivers, hikers, and cyclists.
It uses crowd-sourced [OpenStreetMap](https://www.openstreetmap.org) data and is developed with love by creators of **MapsWithMe** app (later renamed to **Maps.Me**) and by our community.
[Organic Maps](https://organicmaps.app) is a free Android & iOS offline maps app for travellers, tourists, drivers, hikers, and cyclists.
It uses crowd-sourced [OpenStreetMap](https://www.openstreetmap.org) data and is developed with love by the creators of **MapsWithMe** (later renamed to **Maps.Me**) and by our community.
No ads, no tracking, no data collection, no crapware. Your [donations](https://organicmaps.app/donate/) and positive reviews motivate and inspire us, thanks ❤️!
<p float="left">
<a href="https://apps.apple.com/app/organic-maps/id1567437057">
<img src="docs/badges/apple-appstore.png" width="180">
<img alt="Download on the App Store" src="docs/badges/apple-appstore.png" width="180">
</a>
<a href="https://play.google.com/store/apps/details?id=app.organicmaps">
<img src="docs/badges/google-play.png" width="180">
<img alt="Get it on Google Play" src="docs/badges/google-play.png" width="180">
</a>
<a href="https://appgallery.huawei.com/#/app/C104325611">
<img src="docs/badges/huawei-appgallery.png" width="180">
<img alt="Explore it on AppGallery" src="docs/badges/huawei-appgallery.png" width="180">
</a>
<a href="https://f-droid.org/en/packages/app.organicmaps/">
<img src="docs/badges/fdroid.png" width="180">
<img alt="Get it on F-Droid" src="docs/badges/fdroid.png" width="180">
</a>
<a href='https://flathub.org/apps/details/app.organicmaps.desktop'>
<img alt="Download on Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.png" width="180"/>
<img alt="Download on Flathub" src="docs/badges/flathub.png" width="180"/>
</a>
<a href="https://repology.org/project/organicmaps/versions">
<img src="https://repology.org/badge/vertical-allrepos/organicmaps.svg" width="180" alt="Packaging status">
@ -28,22 +28,22 @@ No ads, no tracking, no data collection, no crapware. Your [donations](https://o
</p>
<p float="left">
<img src="android/src/fdroid/play/listings/en-US/graphics/phone-screenshots/1.jpg" width="400" />
<img src="android/src/fdroid/play/listings/en-US/graphics/phone-screenshots/2.jpg" width="400" />
<img src="android/src/fdroid/play/listings/en-US/graphics/phone-screenshots/3.jpg" width="400" />
<img src="android/src/fdroid/play/listings/en-US/graphics/phone-screenshots/4.jpg" width="400" />
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/1.jpg" width="400" />
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/2.jpg" width="400" />
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/3.jpg" width="400" />
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/4.jpg" width="400" />
</p>
## Features
Organic Maps is the ultimate companion app for travelers, tourists, hikers, and cyclists:
Organic Maps is the ultimate companion app for travellers, tourists, hikers, and cyclists:
- Detailed offline maps with places that don't exist on other maps, thanks to [OpenStreetMap](https://osm.org)
- Detailed offline maps with places that don't exist on other maps, thanks to [OpenStreetMap](https://openstreetmap.org)
- Cycling routes, hiking trails, and walking paths
- Contour lines, elevation profiles, peaks, and slopes
- Turn-by-turn walking, cycling, and car navigation with voice guidance
- Fast offline search on the map
- Bookmarks export and import in KML/KMZ formats (GPX is [planned](https://github.com/organicmaps/organicmaps/issues/624))
- Bookmarks and tracks import and export in KML, KMZ & GPX formats
- Dark Mode to protect your eyes
- Countries and regions don't take a lot of space
- Free and open-source
@ -56,7 +56,7 @@ Organic Maps is pure and organic, made with love:
- Saves your battery
- No unexpected mobile data charges
Organic Maps app is free from trackers and other bad stuff:
Organic Maps is free from trackers and other bad stuff:
- No ads
- No tracking
@ -69,11 +69,16 @@ Organic Maps app is free from trackers and other bad stuff:
- No crapware
- ~~No pesticides~~ Purely organic!
The application is verified by <a href="https://reports.exodus-privacy.eu.org/en/reports/app.organicmaps/latest/">Exodus Privacy Project:
The Android application is verified by the <a href="https://reports.exodus-privacy.eu.org/en/reports/app.organicmaps/latest/">Exodus Privacy Project:
<img src="docs/privacy/exodus.png" width="400">
</a>
The iOS application is verified by <a href="https://ios.trackercontrol.org/analysis/app.organicmaps">TrackerControl for iOS:
<img src="docs/privacy/trackercontrol-ios.png" width="400">
</a>
<br/>
Organic Maps doesn't request excessive permissions to spy on you:
@ -87,20 +92,20 @@ At Organic Maps, we believe that privacy is a fundamental human right:
- Organic Maps is an indie community-driven open-source project
- We protect your privacy from Big Tech's prying eyes
- Stay safe no matter wherever you are
- Stay safe no matter where you are
Reject surveillance - embrace your freedom.
[**Give Organic Maps a try!**](#install)
## Who is paying for the free app?
## Who is paying for the development?
The app is free for everyone. Please [donate](https://organicmaps.app/donate) to support us!
The app is free for everyone, so we rely on donations. Please donate at [organicmaps.app/donate](https://organicmaps.app/donate) to support us!
### Our sponsors
[Mythic Beasts](https://www.mythic-beasts.com/) ISP [provides us](https://www.mythic-beasts.com/blog/2021/10/06/improving-the-world-bit-by-expensive-bit/)
two virtual servers with 400 TB/month of free bandwidth to help our users with
two virtual servers with 400 TB/month of free bandwidth to host and serve
maps downloads and updates.
## Copyrights
@ -109,27 +114,27 @@ Licensed under the Apache License, Version 2.0. See
[LICENSE](https://github.com/organicmaps/organicmaps/blob/master/LICENSE),
[NOTICE](https://github.com/organicmaps/organicmaps/blob/master/NOTICE)
and [data/copyright.html](http://htmlpreview.github.io/?https://github.com/organicmaps/organicmaps/blob/master/data/copyright.html)
files for more information.
for more information.
## Governance
See [GOVERNANCE](docs/GOVERNANCE.md).
See [docs/GOVERNANCE.md)](docs/GOVERNANCE.md).
## Contributing
If you want to build the project, check [docs/INSTALL.md](docs/INSTALL.md). If you want to help the project,
see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and read everything in the [docs folder](docs/) of the repository.
see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md). You can [help in many ways](https://organicmaps.app/support-us/), the ability to code is not necessary.
## Beta
Please join our beta program, suggest your features, and report bugs:
- [iOS Beta (TestFlight)](https://testflight.apple.com/join/lrKCl08I)
- [Android Beta (Firebase)](https://appdistribution.firebase.dev/i/9ec3bca5e2b47373)
- [Android Beta (Firebase)](https://appdistribution.firebase.dev/i/2f0fee463107b137)
## Feedback
- **Rate us on [App Store](https://apps.apple.com/app/organic-maps/id1567437057)
- **Rate us on the [App Store](https://apps.apple.com/app/organic-maps/id1567437057)
and [Google Play](https://play.google.com/store/apps/details?id=app.organicmaps)**.
- **Star us on GitHub**.
- Report bugs or issues to [the issue tracker](https://github.com/organicmaps/organicmaps/issues).

47
android/.gitignore vendored
View file

@ -1,40 +1,23 @@
bin
gen
/libs/
.settings
resbuilder
spoon-output
obj
local
.gradle
build
3rd_party/api-android/
RELEASE
.idea
.externalNativeBuild
nativeOutputs
# For now, ignore Android Studio projects
# default android studio ignore list
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
*.class
.classpath
.cproject
.project
local.properties
lint.xml
.gradletasknamecache
# ignore flags symlinks
res/drawable-xhdpi/??.png
res/drawable-xhdpi/do_hack.png
res/drawable-xhdpi/uk_england.png
res/drawable-xhdpi/uk_northern_ireland.png
res/drawable-xhdpi/uk_scotland.png
res/drawable-xhdpi/uk_wales.png
res/drawable-mdpi/??.png
res/drawable-mdpi/do_hack.png
res/drawable-mdpi/uk_england.png
res/drawable-mdpi/uk_northern_ireland.png
res/drawable-mdpi/uk_scotland.png
res/drawable-mdpi/uk_wales.png

View file

@ -1,752 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<uses-feature
android:name="android.hardware.touchscreen"
android:required="true"/>
<uses-feature
android:name="android.hardware.wifi"
android:required="false"/>
<uses-feature
android:name="android.hardware.location"
android:required="false"/>
<uses-feature
android:name="android.hardware.location.network"
android:required="false"/>
<uses-feature
android:name="android.hardware.location.gps"
android:required="false"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--
https://developer.android.com/reference/androidx/core/app/JobIntentService:
When running on Android O, the JobScheduler will take care of wake locks
for you (holding a wake lock from the time you enqueue work until the job
has been dispatched and while it is running). When running on previous
versions of the platform, this wake lock handling is emulated in the
class here by directly calling the PowerManager; this means
the application must request the Manifest.permission.WAKE_LOCK permission.
//-->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!--
Android 13 (API level 33) and higher supports a runtime permission for sending non-exempt (including Foreground
Services (FGS)) notifications from an app.
//-->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE"/>
</intent>
</queries>
<!-- -->
<supports-screens
android:largeScreens="true"
android:xlargeScreens="true"/>
<application
android:name=".MwmApplication"
android:allowBackup="true"
android:backupInForeground="true"
android:fullBackupContent="@xml/backup_content"
android:dataExtractionRules="@xml/backup_content_v31"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:localeConfig="@xml/locales_config"
android:theme="@style/MwmTheme"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="t">
<activity
android:name="app.organicmaps.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="geo"/>
<data android:scheme="ge0"/>
<data android:scheme="om"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="ge0.me"/>
</intent-filter>
<intent-filter android:autoVerify="@bool/autoVerify">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="omaps.app"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:pathPrefix="/maps"/>
<!-- Generated from https://www.google.com/supported_domains //-->
<data android:host="maps.google.ad"/>
<data android:host="maps.google.ae"/>
<data android:host="maps.google.al"/>
<data android:host="maps.google.am"/>
<data android:host="maps.google.as"/>
<data android:host="maps.google.at"/>
<data android:host="maps.google.az"/>
<data android:host="maps.google.ba"/>
<data android:host="maps.google.be"/>
<data android:host="maps.google.bf"/>
<data android:host="maps.google.bg"/>
<data android:host="maps.google.bi"/>
<data android:host="maps.google.bj"/>
<data android:host="maps.google.bs"/>
<data android:host="maps.google.bt"/>
<data android:host="maps.google.by"/>
<data android:host="maps.google.ca"/>
<data android:host="maps.google.cat"/>
<data android:host="maps.google.cd"/>
<data android:host="maps.google.cf"/>
<data android:host="maps.google.cg"/>
<data android:host="maps.google.ch"/>
<data android:host="maps.google.ci"/>
<data android:host="maps.google.cl"/>
<data android:host="maps.google.cm"/>
<data android:host="maps.google.cn"/>
<data android:host="maps.google.co.ao"/>
<data android:host="maps.google.co.bw"/>
<data android:host="maps.google.co.ck"/>
<data android:host="maps.google.co.cr"/>
<data android:host="maps.google.co.id"/>
<data android:host="maps.google.co.il"/>
<data android:host="maps.google.co.in"/>
<data android:host="maps.google.co.jp"/>
<data android:host="maps.google.co.ke"/>
<data android:host="maps.google.co.kr"/>
<data android:host="maps.google.co.ls"/>
<data android:host="maps.google.co.ma"/>
<data android:host="maps.google.co.mz"/>
<data android:host="maps.google.co.nz"/>
<data android:host="maps.google.co.th"/>
<data android:host="maps.google.co.tz"/>
<data android:host="maps.google.co.ug"/>
<data android:host="maps.google.co.uk"/>
<data android:host="maps.google.co.uz"/>
<data android:host="maps.google.co.ve"/>
<data android:host="maps.google.co.vi"/>
<data android:host="maps.google.co.za"/>
<data android:host="maps.google.co.zm"/>
<data android:host="maps.google.co.zw"/>
<data android:host="maps.google.com.af"/>
<data android:host="maps.google.com.ag"/>
<data android:host="maps.google.com.ai"/>
<data android:host="maps.google.com.ar"/>
<data android:host="maps.google.com.au"/>
<data android:host="maps.google.com.bd"/>
<data android:host="maps.google.com.bh"/>
<data android:host="maps.google.com.bn"/>
<data android:host="maps.google.com.bo"/>
<data android:host="maps.google.com.br"/>
<data android:host="maps.google.com.bz"/>
<data android:host="maps.google.com.co"/>
<data android:host="maps.google.com.cu"/>
<data android:host="maps.google.com.cy"/>
<data android:host="maps.google.com.do"/>
<data android:host="maps.google.com.ec"/>
<data android:host="maps.google.com.eg"/>
<data android:host="maps.google.com.et"/>
<data android:host="maps.google.com.fj"/>
<data android:host="maps.google.com.gh"/>
<data android:host="maps.google.com.gi"/>
<data android:host="maps.google.com.gt"/>
<data android:host="maps.google.com.hk"/>
<data android:host="maps.google.com.jm"/>
<data android:host="maps.google.com.kh"/>
<data android:host="maps.google.com.kw"/>
<data android:host="maps.google.com.lb"/>
<data android:host="maps.google.com.ly"/>
<data android:host="maps.google.com.mm"/>
<data android:host="maps.google.com.mt"/>
<data android:host="maps.google.com.mx"/>
<data android:host="maps.google.com.my"/>
<data android:host="maps.google.com.na"/>
<data android:host="maps.google.com.ng"/>
<data android:host="maps.google.com.ni"/>
<data android:host="maps.google.com.np"/>
<data android:host="maps.google.com.om"/>
<data android:host="maps.google.com.pa"/>
<data android:host="maps.google.com.pe"/>
<data android:host="maps.google.com.pg"/>
<data android:host="maps.google.com.ph"/>
<data android:host="maps.google.com.pk"/>
<data android:host="maps.google.com.pr"/>
<data android:host="maps.google.com.py"/>
<data android:host="maps.google.com.qa"/>
<data android:host="maps.google.com.sa"/>
<data android:host="maps.google.com.sb"/>
<data android:host="maps.google.com.sg"/>
<data android:host="maps.google.com.sl"/>
<data android:host="maps.google.com.sv"/>
<data android:host="maps.google.com.tj"/>
<data android:host="maps.google.com.tr"/>
<data android:host="maps.google.com.tw"/>
<data android:host="maps.google.com.ua"/>
<data android:host="maps.google.com.uy"/>
<data android:host="maps.google.com.vc"/>
<data android:host="maps.google.com.vn"/>
<data android:host="maps.google.com"/>
<data android:host="maps.google.cv"/>
<data android:host="maps.google.cz"/>
<data android:host="maps.google.de"/>
<data android:host="maps.google.dj"/>
<data android:host="maps.google.dk"/>
<data android:host="maps.google.dm"/>
<data android:host="maps.google.dz"/>
<data android:host="maps.google.ee"/>
<data android:host="maps.google.es"/>
<data android:host="maps.google.fi"/>
<data android:host="maps.google.fm"/>
<data android:host="maps.google.fr"/>
<data android:host="maps.google.ga"/>
<data android:host="maps.google.ge"/>
<data android:host="maps.google.gg"/>
<data android:host="maps.google.gl"/>
<data android:host="maps.google.gm"/>
<data android:host="maps.google.gr"/>
<data android:host="maps.google.gy"/>
<data android:host="maps.google.hn"/>
<data android:host="maps.google.hr"/>
<data android:host="maps.google.ht"/>
<data android:host="maps.google.hu"/>
<data android:host="maps.google.ie"/>
<data android:host="maps.google.im"/>
<data android:host="maps.google.iq"/>
<data android:host="maps.google.is"/>
<data android:host="maps.google.it"/>
<data android:host="maps.google.je"/>
<data android:host="maps.google.jo"/>
<data android:host="maps.google.kg"/>
<data android:host="maps.google.ki"/>
<data android:host="maps.google.kz"/>
<data android:host="maps.google.la"/>
<data android:host="maps.google.li"/>
<data android:host="maps.google.lk"/>
<data android:host="maps.google.lt"/>
<data android:host="maps.google.lu"/>
<data android:host="maps.google.lv"/>
<data android:host="maps.google.md"/>
<data android:host="maps.google.me"/>
<data android:host="maps.google.mg"/>
<data android:host="maps.google.mk"/>
<data android:host="maps.google.ml"/>
<data android:host="maps.google.mn"/>
<data android:host="maps.google.ms"/>
<data android:host="maps.google.mu"/>
<data android:host="maps.google.mv"/>
<data android:host="maps.google.mw"/>
<data android:host="maps.google.ne"/>
<data android:host="maps.google.nl"/>
<data android:host="maps.google.no"/>
<data android:host="maps.google.nr"/>
<data android:host="maps.google.nu"/>
<data android:host="maps.google.pl"/>
<data android:host="maps.google.pn"/>
<data android:host="maps.google.ps"/>
<data android:host="maps.google.pt"/>
<data android:host="maps.google.ro"/>
<data android:host="maps.google.rs"/>
<data android:host="maps.google.ru"/>
<data android:host="maps.google.rw"/>
<data android:host="maps.google.sc"/>
<data android:host="maps.google.se"/>
<data android:host="maps.google.sh"/>
<data android:host="maps.google.si"/>
<data android:host="maps.google.sk"/>
<data android:host="maps.google.sm"/>
<data android:host="maps.google.sn"/>
<data android:host="maps.google.so"/>
<data android:host="maps.google.sr"/>
<data android:host="maps.google.st"/>
<data android:host="maps.google.td"/>
<data android:host="maps.google.tg"/>
<data android:host="maps.google.tl"/>
<data android:host="maps.google.tm"/>
<data android:host="maps.google.tn"/>
<data android:host="maps.google.to"/>
<data android:host="maps.google.tt"/>
<data android:host="maps.google.vg"/>
<data android:host="maps.google.vu"/>
<data android:host="maps.google.ws"/>
<data android:host="www.googlemaps.com"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:pathPrefix="/maps"/>
<!-- Generated from https://www.google.com/supported_domains //-->
<data android:host="www.google.ad"/>
<data android:host="www.google.ae"/>
<data android:host="www.google.al"/>
<data android:host="www.google.am"/>
<data android:host="www.google.as"/>
<data android:host="www.google.at"/>
<data android:host="www.google.az"/>
<data android:host="www.google.ba"/>
<data android:host="www.google.be"/>
<data android:host="www.google.bf"/>
<data android:host="www.google.bg"/>
<data android:host="www.google.bi"/>
<data android:host="www.google.bj"/>
<data android:host="www.google.bs"/>
<data android:host="www.google.bt"/>
<data android:host="www.google.by"/>
<data android:host="www.google.ca"/>
<data android:host="www.google.cat"/>
<data android:host="www.google.cd"/>
<data android:host="www.google.cf"/>
<data android:host="www.google.cg"/>
<data android:host="www.google.ch"/>
<data android:host="www.google.ci"/>
<data android:host="www.google.cl"/>
<data android:host="www.google.cm"/>
<data android:host="www.google.cn"/>
<data android:host="www.google.co.ao"/>
<data android:host="www.google.co.bw"/>
<data android:host="www.google.co.ck"/>
<data android:host="www.google.co.cr"/>
<data android:host="www.google.co.id"/>
<data android:host="www.google.co.il"/>
<data android:host="www.google.co.in"/>
<data android:host="www.google.co.jp"/>
<data android:host="www.google.co.ke"/>
<data android:host="www.google.co.kr"/>
<data android:host="www.google.co.ls"/>
<data android:host="www.google.co.ma"/>
<data android:host="www.google.co.mz"/>
<data android:host="www.google.co.nz"/>
<data android:host="www.google.co.th"/>
<data android:host="www.google.co.tz"/>
<data android:host="www.google.co.ug"/>
<data android:host="www.google.co.uk"/>
<data android:host="www.google.co.uz"/>
<data android:host="www.google.co.ve"/>
<data android:host="www.google.co.vi"/>
<data android:host="www.google.co.za"/>
<data android:host="www.google.co.zm"/>
<data android:host="www.google.co.zw"/>
<data android:host="www.google.com.af"/>
<data android:host="www.google.com.ag"/>
<data android:host="www.google.com.ai"/>
<data android:host="www.google.com.ar"/>
<data android:host="www.google.com.au"/>
<data android:host="www.google.com.bd"/>
<data android:host="www.google.com.bh"/>
<data android:host="www.google.com.bn"/>
<data android:host="www.google.com.bo"/>
<data android:host="www.google.com.br"/>
<data android:host="www.google.com.bz"/>
<data android:host="www.google.com.co"/>
<data android:host="www.google.com.cu"/>
<data android:host="www.google.com.cy"/>
<data android:host="www.google.com.do"/>
<data android:host="www.google.com.ec"/>
<data android:host="www.google.com.eg"/>
<data android:host="www.google.com.et"/>
<data android:host="www.google.com.fj"/>
<data android:host="www.google.com.gh"/>
<data android:host="www.google.com.gi"/>
<data android:host="www.google.com.gt"/>
<data android:host="www.google.com.hk"/>
<data android:host="www.google.com.jm"/>
<data android:host="www.google.com.kh"/>
<data android:host="www.google.com.kw"/>
<data android:host="www.google.com.lb"/>
<data android:host="www.google.com.ly"/>
<data android:host="www.google.com.mm"/>
<data android:host="www.google.com.mt"/>
<data android:host="www.google.com.mx"/>
<data android:host="www.google.com.my"/>
<data android:host="www.google.com.na"/>
<data android:host="www.google.com.ng"/>
<data android:host="www.google.com.ni"/>
<data android:host="www.google.com.np"/>
<data android:host="www.google.com.om"/>
<data android:host="www.google.com.pa"/>
<data android:host="www.google.com.pe"/>
<data android:host="www.google.com.pg"/>
<data android:host="www.google.com.ph"/>
<data android:host="www.google.com.pk"/>
<data android:host="www.google.com.pr"/>
<data android:host="www.google.com.py"/>
<data android:host="www.google.com.qa"/>
<data android:host="www.google.com.sa"/>
<data android:host="www.google.com.sb"/>
<data android:host="www.google.com.sg"/>
<data android:host="www.google.com.sl"/>
<data android:host="www.google.com.sv"/>
<data android:host="www.google.com.tj"/>
<data android:host="www.google.com.tr"/>
<data android:host="www.google.com.tw"/>
<data android:host="www.google.com.ua"/>
<data android:host="www.google.com.uy"/>
<data android:host="www.google.com.vc"/>
<data android:host="www.google.com.vn"/>
<data android:host="www.google.com"/>
<data android:host="www.google.cv"/>
<data android:host="www.google.cz"/>
<data android:host="www.google.de"/>
<data android:host="www.google.dj"/>
<data android:host="www.google.dk"/>
<data android:host="www.google.dm"/>
<data android:host="www.google.dz"/>
<data android:host="www.google.ee"/>
<data android:host="www.google.es"/>
<data android:host="www.google.fi"/>
<data android:host="www.google.fm"/>
<data android:host="www.google.fr"/>
<data android:host="www.google.ga"/>
<data android:host="www.google.ge"/>
<data android:host="www.google.gg"/>
<data android:host="www.google.gl"/>
<data android:host="www.google.gm"/>
<data android:host="www.google.gr"/>
<data android:host="www.google.gy"/>
<data android:host="www.google.hn"/>
<data android:host="www.google.hr"/>
<data android:host="www.google.ht"/>
<data android:host="www.google.hu"/>
<data android:host="www.google.ie"/>
<data android:host="www.google.im"/>
<data android:host="www.google.iq"/>
<data android:host="www.google.is"/>
<data android:host="www.google.it"/>
<data android:host="www.google.je"/>
<data android:host="www.google.jo"/>
<data android:host="www.google.kg"/>
<data android:host="www.google.ki"/>
<data android:host="www.google.kz"/>
<data android:host="www.google.la"/>
<data android:host="www.google.li"/>
<data android:host="www.google.lk"/>
<data android:host="www.google.lt"/>
<data android:host="www.google.lu"/>
<data android:host="www.google.lv"/>
<data android:host="www.google.md"/>
<data android:host="www.google.me"/>
<data android:host="www.google.mg"/>
<data android:host="www.google.mk"/>
<data android:host="www.google.ml"/>
<data android:host="www.google.mn"/>
<data android:host="www.google.ms"/>
<data android:host="www.google.mu"/>
<data android:host="www.google.mv"/>
<data android:host="www.google.mw"/>
<data android:host="www.google.ne"/>
<data android:host="www.google.nl"/>
<data android:host="www.google.no"/>
<data android:host="www.google.nr"/>
<data android:host="www.google.nu"/>
<data android:host="www.google.pl"/>
<data android:host="www.google.pn"/>
<data android:host="www.google.ps"/>
<data android:host="www.google.pt"/>
<data android:host="www.google.ro"/>
<data android:host="www.google.rs"/>
<data android:host="www.google.ru"/>
<data android:host="www.google.rw"/>
<data android:host="www.google.sc"/>
<data android:host="www.google.se"/>
<data android:host="www.google.sh"/>
<data android:host="www.google.si"/>
<data android:host="www.google.sk"/>
<data android:host="www.google.sm"/>
<data android:host="www.google.sn"/>
<data android:host="www.google.so"/>
<data android:host="www.google.sr"/>
<data android:host="www.google.st"/>
<data android:host="www.google.td"/>
<data android:host="www.google.tg"/>
<data android:host="www.google.tl"/>
<data android:host="www.google.tm"/>
<data android:host="www.google.tn"/>
<data android:host="www.google.to"/>
<data android:host="www.google.tt"/>
<data android:host="www.google.vg"/>
<data android:host="www.google.vu"/>
<data android:host="www.google.ws"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="2gis.ae"/>
<data android:host="2gis.az"/>
<data android:host="2gis.cl"/>
<data android:host="2gis.cl"/>
<data android:host="2gis.com.cy"/>
<data android:host="2gis.cz"/>
<data android:host="2gis.it"/>
<data android:host="2gis.kg"/>
<data android:host="2gis.kz"/>
<data android:host="2gis.ru"/>
<data android:host="2gis.ua"/>
<data android:host="2gis.uz"/>
<data android:host="m.2gis.ae"/>
<data android:host="m.2gis.az"/>
<data android:host="m.2gis.cl"/>
<data android:host="m.2gis.cl"/>
<data android:host="m.2gis.com.cy"/>
<data android:host="m.2gis.cz"/>
<data android:host="m.2gis.it"/>
<data android:host="m.2gis.kg"/>
<data android:host="m.2gis.kz"/>
<data android:host="m.2gis.ru"/>
<data android:host="m.2gis.ua"/>
<data android:host="m.2gis.uz"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"/>
<data android:scheme="https"/>
<!-- #map=$zoom/$lat/$lon -->
<data android:host="www.openstreetmap.org"/>
<data android:path="/"/>
<data android:path="/search"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="mapsme"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="content"/>
<data android:scheme="file"/>
<data android:scheme="data"/>
<data android:host="*"/>
<data android:mimeType="application/vnd.google-earth.kml+xml"/>
<data android:mimeType="application/vnd.google-earth.kmz"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google-earth.kml+xml"/>
<data android:mimeType="application/vnd.google-earth.kmz"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="content"/>
<data android:scheme="file"/>
<data android:scheme="data"/>
<data android:host="*"/>
<data android:mimeType="*/*"/>
<!-- See http://stackoverflow.com/questions/3400072/pathpattern-to-match-file-extension-does-not-work-if-a-period-exists-elsewhere-i -->
<data android:pathPattern="/.*\\.kmz" />
<data android:pathPattern="/.*\\..*\\.kmz" />
<data android:pathPattern="/.*\\..*\\..*\\.kmz" />
<data android:pathPattern="/.*\\..*\\..*\\..*\\.kmz" />
<data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.kmz" />
<data android:pathPattern="/.*\\.kml" />
<data android:pathPattern="/.*\\..*\\.kml" />
<data android:pathPattern="/.*\\..*\\..*\\.kml" />
<data android:pathPattern="/.*\\..*\\..*\\..*\\.kml" />
<data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.kml" />
<!-- Old MAPS.ME binary format //-->
<data android:pathPattern="/.*\\.kmb" />
<data android:pathPattern="/.*\\..*\\.kmb" />
<data android:pathPattern="/.*\\..*\\..*\\.kmb" />
<data android:pathPattern="/.*\\..*\\..*\\..*\\.kmb" />
<data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.kmb" />
</intent-filter>
</activity>
<activity
android:name="app.organicmaps.DownloadResourcesLegacyActivity"
android:configChanges="screenLayout|screenSize"/>
<activity-alias
android:name="app.organicmaps.DownloadResourcesActivity"
android:label="@string/app_name"
android:targetActivity="app.organicmaps.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
<activity
android:name="app.organicmaps.MwmActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"/>
<activity
android:name="app.organicmaps.downloader.DownloaderActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:label="@string/download_maps"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.search.SearchActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:label="@string/search_map"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="stateVisible|adjustResize" />
<activity
android:name="app.organicmaps.settings.SettingsActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:label="@string/settings"
android:parentActivityName="app.organicmaps.MwmActivity" />
<activity
android:name="app.organicmaps.help.HelpActivity"
android:label="@string/about_menu_title"
android:parentActivityName="app.organicmaps.MwmActivity"
android:exported="false">
<intent-filter>
<action android:name="app.organicmaps.help.HelpActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="app.organicmaps.bookmarks.BookmarkCategoriesActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:label="@string/bookmarks"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.bookmarks.BookmarkListActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:label="@string/bookmarks"
android:parentActivityName="app.organicmaps.bookmarks.BookmarkCategoriesActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.editor.EditorActivity"
android:configChanges="orientation|screenLayout|screenSize"
android:label="@string/edit_place"
android:parentActivityName="app.organicmaps.MwmActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="app.organicmaps.editor.ProfileActivity"
android:parentActivityName="app.organicmaps.settings.SettingsActivity" />
<activity
android:name="app.organicmaps.editor.FeatureCategoryActivity"
android:parentActivityName="app.organicmaps.MwmActivity" />
<activity
android:name="app.organicmaps.editor.ReportActivity"
android:parentActivityName="app.organicmaps.MwmActivity" />
<activity
android:name="app.organicmaps.editor.OsmLoginActivity"
android:parentActivityName="app.organicmaps.MwmActivity" />
<activity
android:name="app.organicmaps.bookmarks.BookmarkCategorySettingsActivity"
android:label="@string/list_settings"/>
<activity
android:name="app.organicmaps.widget.placepage.PlaceDescriptionActivity"
android:label="@string/place_description_title"/>
<activity
android:name="app.organicmaps.settings.DrivingOptionsActivity"
android:label="@string/driving_options_title"/>
<service
android:name="app.organicmaps.background.OsmUploadService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<!-- Catches app upgraded intent -->
<receiver
android:name=".background.UpgradeReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${FILE_PROVIDER_PLACEHOLDER}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
<!-- Disable Google's checks for visited sites and loaded URLs in bookmarks description. -->
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" />
<!-- Disable Google's anonymous stats collection -->
<meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" />
</application>
</manifest>

View file

@ -2,7 +2,7 @@ To build, install and run e.g. a Web Debug version on your device/emulator: './g
Or to compile a redistributable Fdroid Beta apk for testing: './gradlew assembleFdroidBeta'
Or to build release apks for all flavors: './gradlew assembleRelease'
Or to build beta apks for all flavors: './gradlew assembleBeta'
To see all available build targets './gradlew tasks'

32
android/app/.gitignore vendored Normal file
View file

@ -0,0 +1,32 @@
/build
/nativeOutputs
# ignore private keys
/google-services.json
/secure.properties
/release.keystore
/secure.properties
/libnotify.properties
/google-services.json
/google-play.json
/firebase-app-distribution.json
/firebase-test-lab.json
/huawei-appgallery.json
/src/main/res/xml/network_security_config.xml
# ignore flags symlinks
/src/main/res/drawable-xhdpi/??.png
/src/main/res/drawable-xhdpi/do_hack.png
/src/main/res/drawable-xhdpi/uk_england.png
/src/main/res/drawable-xhdpi/uk_northern_ireland.png
/src/main/res/drawable-xhdpi/uk_scotland.png
/src/main/res/drawable-xhdpi/uk_wales.png
/src/main/res/drawable-mdpi/??.png
/src/main/res/drawable-mdpi/do_hack.png
/src/main/res/drawable-mdpi/uk_england.png
/src/main/res/drawable-mdpi/uk_northern_ireland.png
/src/main/res/drawable-mdpi/uk_scotland.png
/src/main/res/drawable-mdpi/uk_wales.png
# ignore autogenerated metadata (see prepareGoogleReleaseListing in build.gradle)
/src/google/play/listings

493
android/app/build.gradle Normal file
View file

@ -0,0 +1,493 @@
buildscript {
repositories {
google()
mavenCentral()
}
//
// The magic below is needed to disable Google Mobile Services (a.k.a GMS) and
// Google Firebase Services during the build time. Unfortunately, the only way
// to disable Gradle plugins is to add these hardcore switches to buildscript().
//
// Detect flavors from the task name.
def taskName = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
def isFdroid = taskName.contains('fdroid')
def isBeta = taskName.contains('beta')
//
// Please add symlinks to google/java/app/organicmaps/location for each new gms-enabled flavor below:
// ```
// mkdir -p src/$flavor/java/app/organicmaps/
// ln -sf ../../../../google/java/app/organicmaps/location src/$flavor/java/app/organicmaps/
// ls -la src/$flavor/java/app/organicmaps/location/GoogleFusedLocationProvider.java
// ```
ext.googleMobileServicesEnabled = taskName.contains('google') || taskName.contains('huawei') || taskName.contains('web')
// Firebase Crashlytics compile-time feature flag: -Pfirebase=true|false
def googleFirebaseServicesFlag = findProperty('firebase')
// Enable Firebase for all beta flavors except fdroid only if google-services.json exists.
def googleFirebaseServicesDefault = isBeta && !isFdroid && file("$projectDir/google-services.json").exists()
ext.googleFirebaseServicesEnabled = googleFirebaseServicesFlag != null ?
googleFirebaseServicesFlag == '' || googleFirebaseServicesFlag.toBoolean() :
googleFirebaseServicesDefault
dependencies {
classpath 'com.android.tools.build:gradle:8.2.1'
if (googleMobileServicesEnabled) {
println('Building with Google Mobile Services')
classpath 'com.google.gms:google-services:4.4.0'
} else {
println('Building without Google Services')
}
if (googleFirebaseServicesEnabled) {
println('Building with Google Firebase Services')
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
classpath 'com.google.firebase:firebase-appdistribution-gradle:4.0.1'
} else {
println('Building without Google Firebase Services')
}
classpath('com.github.triplet.gradle:play-publisher:3.8.6')
classpath('ru.cian:huawei-publish-gradle-plugin:1.4.0')
}
}
repositories {
google()
mavenCentral()
maven { url 'https://www.jitpack.io' } // MPAndroidChart
}
apply plugin: 'com.android.application'
apply from: 'secure.properties'
if (googleMobileServicesEnabled) {
apply plugin: 'com.google.gms.google-services'
}
if (googleFirebaseServicesEnabled) {
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.firebase.appdistribution'
}
apply plugin: 'com.github.triplet.play'
apply plugin: 'ru.cian.huawei-publish-gradle-plugin'
dependencies {
// Google Mobile Services
if (googleMobileServicesEnabled) {
implementation 'com.google.android.gms:play-services-location:21.0.1'
}
// Google Firebase Services
if (googleFirebaseServicesEnabled) {
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:32.7.1')
// Add the dependencies for the Crashlytics and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-crashlytics-ndk'
}
// This line is added as a workaround for duplicate classes error caused by some outdated dependency:
// > A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
// We don't use Kotlin, but some dependencies are actively using it.
// See https://stackoverflow.com/a/75719642
implementation 'androidx.core:core:1.12.0'
implementation(platform('org.jetbrains.kotlin:kotlin-bom:1.9.22'))
implementation 'androidx.annotation:annotation:1.7.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.car.app:app:1.4.0-rc02'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.fragment:fragment:1.6.2'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.work:work-runtime:2.9.0'
implementation 'androidx.lifecycle:lifecycle-process:2.7.0'
implementation 'com.google.android.material:material:1.11.0'
// Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture
// https://github.com/organicmaps/organicmaps/issues/6106
implementation 'com.google.guava:guava:32.1.3-android'
implementation 'com.github.devnullorthrow:MPAndroidChart:3.2.0-alpha'
implementation 'net.jcip:jcip-annotations:1.0'
// Test Dependencies
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.8.0'
testImplementation 'org.mockito:mockito-inline:5.2.0'
}
def run(cmd) {
def stdout = new ByteArrayOutputStream()
exec {
commandLine = cmd
standardOutput = stdout
}
return stdout.toString()
}
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
def getVersion() {
def isWindows = DefaultNativePlatform.getCurrentOperatingSystem().isWindows()
def bash = isWindows ? 'C:\\Program Files\\Git\\bin\\bash.exe' : 'bash'
def versionCode = Integer.parseInt(run([bash, '../../tools/unix/version.sh', 'android_code']).trim())
def versionName = run([bash, '../../tools/unix/version.sh', 'android_name']).trim()
return new Tuple2(versionCode, versionName)
}
def getCommitMessage() {
return run(['git', '--no-pager', 'show', '-s', '--format=%s%n%n%b', 'HEAD']).trim()
}
def osName = System.properties['os.name'].toLowerCase()
project.ext.appId = 'app.organicmaps'
project.ext.appName = 'Organic Maps'
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
android {
namespace 'app.organicmaps'
buildFeatures {
dataBinding = true
buildConfig = true
}
// All properties are read from gradle.properties file
compileSdk propCompileSdkVersion.toInteger()
ndkVersion '26.1.10909125'
defaultConfig {
// Default package name is taken from the manifest and should be app.organicmaps
def ver = getVersion()
versionCode = ver.V1
versionName = ver.V2
println('Version: ' + versionName)
println('VersionCode: ' + versionCode)
minSdk propMinSdkVersion.toInteger()
targetSdk propTargetSdkVersion.toInteger()
applicationId project.ext.appId
buildConfigField 'String', 'SUPPORT_MAIL', '"android@organicmaps.app"'
// Should be customized in flavors.
buildConfigField 'String', 'REVIEW_URL', '""'
resourceConfigurations += [project.ext.supportedLocalizations]
externalNativeBuild {
def pchFlag = 'OFF'
if (project.hasProperty('pch')) pchFlag = 'ON'
def njobs = ''
if (project.hasProperty('njobs')) njobs = project.getProperty('njobs')
cmake {
cppFlags '-fexceptions', '-frtti'
// There is no sense to enable sections without gcc's --gc-sections flag.
cFlags '-fno-function-sections', '-fno-data-sections',
'-Wno-extern-c-compat'
arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static',
"-DOS=$osName", '-DSKIP_TESTS=ON', '-DSKIP_TOOLS=ON', "-DUSE_PCH=$pchFlag",
"-DNJOBS=$njobs"
targets 'organicmaps'
}
}
// Use, for example, -Parm32 gradle parameter to build only for armeabi-v7a.
ndk {
abiFilters = new HashSet<>()
if (project.hasProperty('arm32') || project.hasProperty('armeabi-v7a')) {
abiFilters.add('armeabi-v7a')
}
if (project.hasProperty('arm64') || project.hasProperty('arm64-v8a')) {
abiFilters.add('arm64-v8a')
}
if (project.hasProperty('x86')) {
abiFilters.add('x86')
}
if (project.hasProperty('x86_64') || project.hasProperty('x64')) {
abiFilters.add('x86_64')
}
if (abiFilters.isEmpty()) {
abiFilters.add('armeabi-v7a')
abiFilters.add('arm64-v8a')
// For the emulator, chromebooks and some Intel Atom devices.
abiFilters.add('x86_64')
}
println('Building for ' + abiFilters + ' archs.')
}
setProperty('archivesBaseName', appName.replaceAll('\\s','') + '-' + defaultConfig.versionCode)
}
flavorDimensions += 'default'
productFlavors {
// 01 is a historical artefact, sorry.
final int HUAWEI_VERSION_CODE_BASE = 01_00_00_00_00
google {
dimension 'default'
versionName = android.defaultConfig.versionName + '-Google'
buildConfigField 'String', 'SUPPORT_MAIL', '"googleplay@organicmaps.app"'
buildConfigField 'String', 'REVIEW_URL', '"market://details?id=app.organicmaps"'
}
web {
dimension 'default'
versionName = android.defaultConfig.versionName + '-Web'
buildConfigField 'String', 'SUPPORT_MAIL', '"apk@organicmaps.app"'
}
fdroid {
dimension 'default'
versionName = android.defaultConfig.versionName + '-FDroid'
buildConfigField 'String', 'SUPPORT_MAIL', '"fdroid@organicmaps.app"'
}
huawei {
dimension 'default'
versionName = android.defaultConfig.versionName + '-Huawei'
versionCode = HUAWEI_VERSION_CODE_BASE + android.defaultConfig.versionCode
buildConfigField 'String', 'SUPPORT_MAIL', '"huawei@organicmaps.app"'
buildConfigField 'String', 'REVIEW_URL', '"appmarket://details?id=app.organicmaps"'
}
}
playConfigs {
googleRelease {
enabled.set(true)
}
}
splits.abi {
boolean enabled = project.hasProperty('splitApk')
println ('Create separate apks: ' + enabled)
enable enabled
reset()
include 'x86', 'armeabi-v7a', 'arm64-v8a', 'x86_64'
universalApk true
}
lint {
disable 'MissingTranslation'
// https://github.com/organicmaps/organicmaps/issues/3551
disable 'MissingQuantity', 'UnusedQuantity'
// https://github.com/organicmaps/organicmaps/issues/3550
disable 'ByteOrderMark'
// https://github.com/organicmaps/organicmaps/issues/1077
disable 'CustomSplashScreen'
// https://github.com/organicmaps/organicmaps/issues/3610
disable 'InsecureBaseConfiguration'
abortOnError true
}
gradle.projectsEvaluated {
android.applicationVariants.all { variant ->
def task = variant.name.capitalize()
project.task(type: Exec, "run${task}", dependsOn: "install${task}") {
commandLine android.getAdbExe(), 'shell', 'am', 'start', '-n', "$applicationId/app.organicmaps.DownloadResourcesActivity", '-a', 'android.intent.action.MAIN', '-c', 'android.intent.category.LAUNCHER'
}
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword '12345678'
keyAlias 'debug'
keyPassword '12345678'
}
release {
storeFile file(spropStoreFile)
storePassword spropStorePassword
keyAlias spropKeyAlias
keyPassword spropKeyPassword
}
}
buildTypes {
debug {
applicationIdSuffix '.debug' // Allows to install debug and release builds together
versionNameSuffix '-debug'
jniDebuggable true // Enable jni debug build
zipAlignEnabled true
signingConfig signingConfigs.debug
resValue 'string', 'app_id', android.defaultConfig.applicationId + applicationIdSuffix
resValue 'string', 'app_name', project.ext.appName + ' ' + '(Debug)'
// Do not generate separate debug symbols for debug apps, because we don't distribute them.
ndk.debugSymbolLevel = 'none'
if (googleFirebaseServicesEnabled) {
// Keep debug symbols for test lab.
ndk.debugSymbolLevel = 'symbol_table'
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
}
}
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
// Includes the default ProGuard rules files that are packaged with the Android Gradle plugin.
// To learn more, go to the documentation section about R8 configuration files.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
resValue 'string', 'app_id', android.defaultConfig.applicationId
resValue 'string', 'app_name', project.ext.appName
// Full size symbols are too big for Google, 217mb aab vs 95mb.
ndk.debugSymbolLevel = 'symbol_table'
if (googleFirebaseServicesEnabled) {
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
}
}
beta {
applicationIdSuffix '.beta'
versionNameSuffix '-beta'
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
// Includes the default ProGuard rules files that are packaged with the Android Gradle plugin.
// To learn more, go to the documentation section about R8 configuration files.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
matchingFallbacks = ['debug', 'release']
resValue 'string', 'app_id', android.defaultConfig.applicationId + applicationIdSuffix
resValue 'string', 'app_name', project.ext.appName + ' ' + '(Beta)'
// Full size symbols are too big for Google, 217mb aab vs 95mb.
ndk.debugSymbolLevel = 'symbol_table'
if (googleFirebaseServicesEnabled) {
firebaseCrashlytics {
nativeSymbolUploadEnabled true
}
firebaseAppDistribution {
// A new beta release is created for each commit.
// Use the last commit message for the release notes.
releaseNotes = getCommitMessage()
groups = 'qa' // Notify only selected people.
serviceCredentialsFile = "$projectDir/firebase-app-distribution.json"
}
}
}
}
externalNativeBuild {
cmake {
version '3.22.1+'
buildStagingDirectory './nativeOutputs'
path '../../CMakeLists.txt'
}
}
// We don't compress these extensions in assets/ because our random FileReader can't read zip-compressed files from apk.
// TODO: Load all minor files via separate call to ReadAsString which can correctly handle compressed files in zip containers.
androidResources {
ignoreAssetsPattern '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj']
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
packagingOptions.jniLibs {
excludes += [
'lib/**/libVkLayer_khronos_validation.so',
'lib/**/libVkLayer_core_validation.so',
'lib/**/libVkLayer_threading.so',
'lib/**/libVkLayer_image.so',
'lib/**/libVkLayer_parameter_validation.so',
'lib/**/libVkLayer_object_tracker.so',
'lib/**/libVkLayer_swapchain.so',
'lib/**/libVkLayer_unique_objects.so',
]
}
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}
android.buildTypes.all { buildType ->
def suffix = applicationIdSuffix != null ? applicationIdSuffix : ""
def authorityValue = android.defaultConfig.applicationId + suffix + ".provider"
def authority = "\"" + authorityValue + "\""
buildConfigField 'String', 'FILE_PROVIDER_AUTHORITY', authority
manifestPlaceholders += [FILE_PROVIDER_PLACEHOLDER : authorityValue]
}
task prepareGoogleReleaseListing {
// Prepares Google Play metainfo from F-Droid metainfo.
final sourceFlavor = 'fdroid'
final targetFlavor = 'google'
doLast {
final sourceDir = new File("${projectDir}/src/$sourceFlavor/play/listings")
final targetDir = new File("${projectDir}/src/$targetFlavor/play/listings")
final sourceFiles = fileTree(dir: sourceDir,
include: '**/*.txt', exclude: "**/*-${targetFlavor}.txt")
sourceFiles.each { File sourceFile ->
final locale = sourceFile.parentFile.getName()
final targetLocaleDir = new File(targetDir, locale)
if (!targetLocaleDir.isDirectory())
targetLocaleDir.mkdirs()
final targetFile = new File(targetLocaleDir, sourceFile.getName())
// Override Google-specific values by using ${name}-google.txt files.
final overrideFile = new File(sourceFile.getPath().replace('.txt', "-${targetFlavor}.txt"))
targetFile.text = overrideFile.exists() ? overrideFile.text : sourceFile.text
}
copy {
from "${projectDir}/../../screenshots/android"
into targetDir
}
}
}
play {
enabled.set(false)
track.set('production')
userFraction.set(Double.valueOf(0.10)) // 10%
defaultToAppBundles.set(true)
releaseStatus.set(ReleaseStatus.IN_PROGRESS)
serviceAccountCredentials.set(file('google-play.json'))
}
huaweiPublish {
instances {
huaweiRelease {
credentialsPath = "$projectDir/huawei-appgallery.json"
buildFormat = 'aab'
deployType = 'draft' // confirm manually
releaseNotes = []
def localeOverride = [
'am' : 'am-ET',
'gu': 'gu_IN',
'iw-IL': 'he_IL',
'kn-IN': 'kn_IN',
'ml-IN': 'ml_IN',
'mn-MN': 'mn_MN',
'mr-IN': 'mr_IN',
'ta-IN': 'ta_IN',
'te-IN': 'te_IN',
]
def files = fileTree(dir: "$projectDir/src/fdroid/play/listings",
include: '**/release-notes.txt')
files.each { File file ->
def path = file.getPath()
def locale = file.parentFile.getName()
locale = localeOverride.get(locale, locale)
releaseNotes.add(new ru.cian.huawei.publish.ReleaseNote(locale, path))
}
}
}
}

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View file

30
android/app/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,30 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# For Guava used by Android Auto
-dontwarn java.lang.reflect.AnnotatedType
# Disable obfuscation since it is open-source app.
-dontobfuscate
# R8 crypts the source line numbers in all log messages.
# https://github.com/organicmaps/organicmaps/issues/6559#issuecomment-1812039926
-dontoptimize

View file

@ -0,0 +1,28 @@
package app.organicmaps;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest
{
@Test
public void useAppContext()
{
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("app.organicmaps", appContext.getPackageName());
}
}

View file

@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:gwpAsanMode="always" />
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#B97647</color>
</resources>

View file

@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:gwpAsanMode="always" />
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Some files were not shown because too many files have changed in this diff Show more