Compare commits

..

20 Commits

Author SHA1 Message Date
WerWolv
a6cc4ca210 Set native compiler to gcc 2023-11-04 15:02:39 +01:00
WerWolv
b4f6c8d773 Try to get libromfs to build again 2023-11-04 14:57:26 +01:00
WerWolv
effe93ddd8 Try fix sysroot settings 2023-11-04 14:27:40 +01:00
WerWolv
84b4c14d35 Don't cancel workflows if one fails in matrix 2023-11-04 13:55:23 +01:00
WerWolv
911164b513 Try force setting OSX Arch 2023-11-04 13:50:05 +01:00
WerWolv
411214797b Add cross compiling message 2023-11-03 16:16:45 +01:00
WerWolv
5206a712fe Use toolchain file to cross compile 2023-11-03 16:15:16 +01:00
WerWolv
641949ecda Set native compiler 2023-11-03 16:01:54 +01:00
WerWolv
eadf9c1c2e Don't use -target anymore 2023-11-03 15:41:26 +01:00
WerWolv
ed37d56625 Remove minor version number from build target 2023-11-03 14:18:28 +01:00
WerWolv
64185a0d2f Fixed target again 2023-11-03 14:06:08 +01:00
WerWolv
aa72cd4d24 Only update brew packages on ARM 2023-11-03 14:00:01 +01:00
WerWolv
7dbf84f73a Fixed build target tripple 2023-11-03 13:23:43 +01:00
WerWolv
f077515a46 Upgrade to macOS 12 builds 2023-11-03 13:16:33 +01:00
WerWolv
bb43af3fc9 Back to standard llvm 2023-11-03 12:55:40 +01:00
WerWolv
94c0b663f6 Try to use pre-built version 2023-11-03 12:47:00 +01:00
WerWolv
cac656710e Try using llvm17 directly 2023-11-03 08:10:32 +01:00
WerWolv
df807896ea Try install latest llvm
.
2023-11-02 22:25:24 +01:00
WerWolv
31b63a11ce Try fixing build 2023-11-02 21:33:29 +01:00
WerWolv
211f775b9f git: Try cross-compiling 2023-11-02 20:49:11 +01:00
557 changed files with 201478 additions and 98188 deletions

View File

@@ -65,5 +65,4 @@ readability-*,
-readability-redundant-access-specifiers,
-readability-function-cognitive-complexity,
-readability-identifier-naming,
*-include-cleaner,
-readability-qualified-auto'
-readability-qualified-auto'

View File

@@ -1,5 +0,0 @@
cmake-build-*/
build*/
local/
**/Dockerfile

View File

@@ -6,11 +6,4 @@ skip -rfu ^__gnu_debug::
skip -rfu ^ImGui::
# Trigger breakpoint when execution reaches triggerSafeShutdown()
break triggerSafeShutdown
# Print backtrace after execution jumped to an invalid address
define fixbt
set $pc = *(void **)$rsp
set $rsp = $rsp + 8
bt
end
break triggerSafeShutdown

5
.gitattributes vendored
View File

@@ -1,4 +1 @@
lib/external/** linguist-vendored
dist/*.sh eol=lf
dist/**/*Dockerfile eol=lf
lib/external/** linguist-vendored

View File

@@ -46,7 +46,6 @@ jobs:
- name: 🛠️ Build
run: |
set -x
mkdir -p build
cd build
CC=gcc-12 CXX=g++-12 cmake \

View File

@@ -63,7 +63,7 @@ jobs:
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.100'
dotnet-version: '7.0.x'
- name: 📜 Set version variable
run: |
@@ -72,14 +72,13 @@ jobs:
# Windows cmake build
- name: 🛠️ Build
run: |
set -x
mkdir -p build
cd build
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DIMHEX_GENERATE_PACKAGE=ON \
-DCREATE_PACKAGE=ON \
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
@@ -95,17 +94,15 @@ jobs:
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
- name: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Windows Installer x86_64
path: |
imhex-*.msi
- name: ⬆️ Upload Portable ZIP
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Windows Portable x86_64
path: |
build/install/*
@@ -113,16 +110,14 @@ jobs:
- name: ⬇️ Download Mesa3D for NoGPU version
shell: bash
run: |
set -x
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
curl https://werwolv.net/downloads/mesa/MesaForWindows-x64-latest.7z -L -o mesa.7z
7z e mesa.7z
mv opengl32.dll build/install
- name: ⬆️ Upload NoGPU Portable ZIP
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Windows Portable NoGPU x86_64
path: |
build/install/*
@@ -137,10 +132,18 @@ jobs:
include:
- suffix: "-NoGPU"
custom_glfw: true
toolchain_file: ""
needs_update: true
- suffix: ""
custom_glfw: false
toolchain_file: ""
needs_update: true
- suffix: "-ARM"
custom_glfw: false
toolchain_file: "dist/macOS/macos_arm_toolchain.cmake"
needs_update: true
name: 🍎 macOS 12.0${{matrix.suffix}}
name: 🍎 macOS 11.0${{matrix.suffix}}
steps:
- name: 🧰 Checkout
@@ -166,10 +169,13 @@ jobs:
build/CMakeCache.txt
key: ${{ runner.os }}-${{ matrix.suffix }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Update brew packages
if: ${{matrix.needs_update}}
run: |
brew update
- name: ⬇️ Install dependencies
run: |
set -x
brew reinstall python || brew link --overwrite python
brew bundle --no-lock --file dist/Brewfile
rm -rf /usr/local/Cellar/capstone
@@ -181,7 +187,7 @@ jobs:
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.100'
dotnet-version: '7.0.x'
- name: 🧰 Checkout glfw
if: ${{matrix.custom_glfw}}
@@ -194,7 +200,6 @@ jobs:
- name: ⬇️ Patch and install custom glfw
if: ${{matrix.custom_glfw}}
run: |
set -x
cd glfw
git apply ../dist/macOS/0001-glfw-SW.patch
@@ -214,21 +219,24 @@ jobs:
# MacOS cmake build
- name: 🛠️ Build
run: |
set -x
mkdir -p build
cd build
CC=$(brew --prefix gcc@12)/bin/gcc-12 \
CXX=$(brew --prefix gcc@12)/bin/g++-12 \
CC=$(brew --prefix llvm)/bin/clang \
CXX=$(brew --prefix llvm)/bin/clang++ \
OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DIMHEX_GENERATE_PACKAGE=ON \
-DCMAKE_TOOLCHAIN_FILE="${{matrix.toolchain_file}}" \
-DCREATE_BUNDLE=ON \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DNATIVE_CMAKE_C_COMPILER="$(brew --prefix gcc@12)/bin/gcc-12" \
-DNATIVE_CMAKE_CXX_COMPILER="$(brew --prefix gcc@12)/bin/g++-12" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
@@ -238,56 +246,14 @@ jobs:
ninja package
- name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: macOS DMG${{matrix.suffix}} x86_64
path: build/*.dmg
macos-arm64:
runs-on: ubuntu-22.04
name: 🍎 macOS 12.1 arm64
steps:
- name: 🧰 Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v3
with:
path: cache
key: build-macos-arm64-cache
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2.1.2 # Doesn't work with a MacOS runner ?
with:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/macOS/arm64.Dockerfile --progress=plain --build-arg 'JOBS=4' --build-arg "BUILD_TYPE=$(BUILD_TYPE)" --build-context imhex=$(pwd) --output out
- name: ⬆️ Upload artifacts
uses: actions/upload-artifact@v4
with:
name: macOS ZIP arm64
path: out/
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
- name: 🗑️ Delete old cache
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
gh extension install actions/gh-actions-cache
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
# Ubuntu build
ubuntu:
strategy:
fail-fast: false
matrix:
include:
- name: Ubuntu
@@ -333,7 +299,7 @@ jobs:
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.100'
dotnet-version: '7.0.x'
- name: 🏔️ Set Environment variables
run: |
@@ -344,7 +310,6 @@ jobs:
# Ubuntu cmake build
- name: 🛠️ Build
run: |
set -x
git config --global --add safe.directory '*'
mkdir -p build
cd build
@@ -374,9 +339,8 @@ jobs:
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
- name: ⬆️ Upload DEB
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Ubuntu ${{ matrix.release_num }} DEB x86_64
path: '*.deb'
@@ -410,16 +374,14 @@ jobs:
- name: ⬆️ Upload AppImage
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Linux AppImage x86_64
path: 'out/*.AppImage'
- name: ⬆️ Upload AppImage zsync
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Linux AppImage zsync x86_64
path: 'out/*.AppImage.zsync'
@@ -452,7 +414,7 @@ jobs:
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.100'
dotnet-version: '7.0.x'
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
@@ -471,7 +433,6 @@ jobs:
# ArchLinux cmake build
- name: 🛠️ Build
run: |
set -x
mkdir -p build
cd build
CC=gcc CXX=g++ cmake -G "Ninja" \
@@ -504,7 +465,6 @@ jobs:
# makepkg doesn't want to run as root, so I had to chmod 777 all over
- name: 📦 Package ArchLinux .pkg.tar.zst
run: |
set -x
cd build
# the name is a small trick to make makepkg recognize it as the source
@@ -520,9 +480,8 @@ jobs:
mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: ArchLinux .pkg.tar.zst x86_64
path: |
build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
@@ -537,14 +496,14 @@ jobs:
mock_release: rawhide
release_num: rawhide
mock_config: fedora-rawhide
- name: Fedora
mock_release: f39
release_num: 39
mock_config: fedora-39
- name: Fedora
mock_release: f38
release_num: 38
mock_config: fedora-38
- name: Fedora
mock_release: f37
release_num: 37
mock_config: fedora-37
- name: RHEL-AlmaLinux
mock_release: epel9
release_num: 9
@@ -577,7 +536,6 @@ jobs:
- name: ⬇️ Update all packages and install dependencies
run: |
set -x
dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y
dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \
fedpkg \
@@ -586,7 +544,7 @@ jobs:
- name: ⬇️ Install .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.100'
dotnet-version: '7.0.x'
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1.2.5
@@ -648,9 +606,8 @@ jobs:
$GITHUB_WORKSPACE/imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
- name: ⬆️ Upload RPM
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
path: |
imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm

View File

@@ -29,7 +29,7 @@ jobs:
uses: actions/cache@v3
with:
path: cache
key: web-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
key: build-web-cache
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2.1.2
@@ -43,7 +43,9 @@ jobs:
- name: 🔨 Fix permissions
run: |
chmod -c -R +rX "out/"
chmod -c -R +rX "out/" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
- name: ⬆️ Upload artifacts
uses: actions/upload-pages-artifact@v2

View File

@@ -21,7 +21,6 @@ jobs:
- name: 📜 Verify version and set version variable
run: |
set -x
project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}"
@@ -65,7 +64,6 @@ jobs:
- name: 📜 Verify version and set version variable
run: |
set -x
project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}"
@@ -89,8 +87,7 @@ jobs:
skip_unpack: true
- name: 🗜️ Unzip files when needed
run: |
set -x
run: |
for zipfile in ./*.zip
do
if [ `zipinfo -1 "$zipfile" | wc -l` -eq 1 ];
@@ -115,7 +112,6 @@ jobs:
- name: ✒️ Prepare PKGBUILD
run: |
set -x
cp ImHex/dist/Arch/PKGBUILD .
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`

View File

@@ -44,7 +44,6 @@ jobs:
- name: 🛠️ Build
run: |
set -x
mkdir -p build
cd build
CC=gcc-12 CXX=g++-12 cmake \

1
.gitignore vendored
View File

@@ -3,7 +3,6 @@
cmake-build-*/
build*/
local/
venv/
*.mgc

27
.gitmodules vendored
View File

@@ -1,25 +1,25 @@
[submodule "lib/third_party/nativefiledialog"]
path = lib/third_party/nativefiledialog
[submodule "lib/external/nativefiledialog"]
path = lib/external/nativefiledialog
url = https://github.com/btzy/nativefiledialog-extended
ignore = dirty
[submodule "lib/third_party/yara/yara"]
path = lib/third_party/yara/yara
[submodule "lib/external/yara/yara"]
path = lib/external/yara/yara
url = https://github.com/VirusTotal/yara
ignore = dirty
[submodule "lib/third_party/xdgpp"]
path = lib/third_party/xdgpp
[submodule "lib/external/xdgpp"]
path = lib/external/xdgpp
url = https://git.sr.ht/~danyspin97/xdgpp
ignore = dirty
[submodule "lib/third_party/fmt"]
path = lib/third_party/fmt
[submodule "lib/external/fmt"]
path = lib/external/fmt
url = https://github.com/fmtlib/fmt
ignore = dirty
[submodule "lib/third_party/capstone"]
path = lib/third_party/capstone
[submodule "lib/external/capstone"]
path = lib/external/capstone
url = https://github.com/capstone-engine/capstone
ignore = dirty
[submodule "lib/third_party/jthread/jthread"]
path = lib/third_party/jthread/jthread
[submodule "lib/external/jthread/jthread"]
path = lib/external/jthread/jthread
url = https://github.com/josuttis/jthread
ignore = dirty
@@ -33,6 +33,3 @@
path = lib/external/libwolv
url = https://github.com/WerWolv/libwolv
[submodule "lib/third_party/HashLibPlus"]
path = lib/third_party/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus

View File

@@ -14,8 +14,6 @@ option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON)
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. Only usable on Windows and MacOS" OFF)
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
# Basic compiler and cmake configurations
set(CMAKE_CXX_STANDARD 23)
@@ -39,7 +37,12 @@ setDefaultBuiltTypeIfUnset()
detectBadClone()
verifyCompiler()
detectBundledPlugins()
# List plugin names here. Project name must match folder name
set(PLUGINS
builtin
windows
script_loader
)
# Add various defines
detectOS()
@@ -62,4 +65,3 @@ add_subdirectory(tests EXCLUDE_FROM_ALL)
# Configure packaging
createPackage()
generatePDBs()
generateSDKDirectory()

290
README.md
View File

@@ -51,259 +51,86 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
## Screenshots
![Hex editor, patterns and data information](https://private-user-images.githubusercontent.com/10835354/290512928-ae20c3ce-4c02-4579-9471-640f43fd6bad.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDMyNDk0NTksIm5iZiI6MTcwMzI0OTE1OSwicGF0aCI6Ii8xMDgzNTM1NC8yOTA1MTI5MjgtYWUyMGMzY2UtNGMwMi00NTc5LTk0NzEtNjQwZjQzZmQ2YmFkLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFJV05KWUFYNENTVkVINTNBJTJGMjAyMzEyMjIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjMxMjIyVDEyNDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTFmN2RhYmNlYWVjYzI0YWQxNjE0YjI1NDNjMTQ2MGFlODhkMmYzMTVkY2Y3MzNlYzUzYTM3N2IwNWE4OGY2YTAmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.RbVnFXxuJS0xUoWbdgqCHtd-BopaFCyDypAfgkzGezU)
![Hex editor, patterns and data information](https://user-images.githubusercontent.com/10835354/139717326-8044769d-527b-4d88-8adf-2d4ecafdca1f.png)
![Bookmarks, disassembler and data processor](https://user-images.githubusercontent.com/10835354/139717323-1f8c9d52-f7eb-4f43-9f11-097ac728ed6c.png)
<details>
<summary><strong>More Screenshots</strong></summary>
![Data Processor decrypting some data and displaying it as an image](https://private-user-images.githubusercontent.com/10835354/290514353-d7f53f91-09e9-46c4-a720-e979c1c4e820.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDMyNDk0NTksIm5iZiI6MTcwMzI0OTE1OSwicGF0aCI6Ii8xMDgzNTM1NC8yOTA1MTQzNTMtZDdmNTNmOTEtMDllOS00NmM0LWE3MjAtZTk3OWMxYzRlODIwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFJV05KWUFYNENTVkVINTNBJTJGMjAyMzEyMjIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjMxMjIyVDEyNDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWE4OGIxNjg0NDcyMWVkYTMzOTAzMTAxMmJlNjE2ZjVkMTVmNzhlMDU1ZWNhODQyZjNjYTgzMzgzYjYyODVlNzQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Y4VAVgSPBZI3Q1gDehPuoC98pQXVe-z9FUWhvDAV-1g)
![STL Parser written in the Pattern Language visualizing a 3D model](https://private-user-images.githubusercontent.com/10835354/290517253-426d83c5-f6b7-4b69-aa87-05e48ab73e24.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDMyNDk0NTksIm5iZiI6MTcwMzI0OTE1OSwicGF0aCI6Ii8xMDgzNTM1NC8yOTA1MTcyNTMtNDI2ZDgzYzUtZjZiNy00YjY5LWFhODctMDVlNDhhYjczZTI0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFJV05KWUFYNENTVkVINTNBJTJGMjAyMzEyMjIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjMxMjIyVDEyNDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJlMmJmZDYzOTgyZGYxOWQ5MmJhMTMyMzA2YWE3YmU0ODJlY2MwYmQxM2RlODc1MTgwYTQ5ZGYxMWNkY2JlNjAmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.lsJSbAnAWZNXm_bteUWZUM96Nd4qKhk3H3WZtjsFQB4)
![Data Information view displaying various stats about the file](https://private-user-images.githubusercontent.com/10835354/290517882-1601cd05-e50b-41f7-8272-cb9af9e6fb81.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDMyNDk0NTksIm5iZiI6MTcwMzI0OTE1OSwicGF0aCI6Ii8xMDgzNTM1NC8yOTA1MTc4ODItMTYwMWNkMDUtZTUwYi00MWY3LTgyNzItY2I5YWY5ZTZmYjgxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFJV05KWUFYNENTVkVINTNBJTJGMjAyMzEyMjIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjMxMjIyVDEyNDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRlZjNmNDA4NThlZjFmOTdmYWVlNGIxODQ3MDdmZDkzZGM4ZDEwOWZmNWRiMmM3NjNlODFiMTQ5ZTFhZTRlOTMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.AWm3GajW2KkNMT7AWhhCYca18UbXqZCS3-8RG4YN_ng)
</details>
## Features
<details>
<summary><strong>Featureful hex view</strong></summary>
- Featureful hex view
- Byte patching
- Patch management
- Infinite Undo/Redo
- "Copy bytes as..."
- Copy bytes as feature
- Bytes
- Hex string
- C, C++, C#, Rust, Python, Java & JavaScript array
- ASCII-Art hex view
- HTML self-contained div
- Simple string and hex search
- Goto from start, end and current cursor position
- String and hex search
- Colorful highlighting
- Configurable foreground highlighting rules
- Background highlighting using patterns, find results and bookmarks
- Displaying data as a list of many different types
- Hexadecimal integers (8, 16, 32, 64 bit)
- Signed and unsigned decimal integers (8, 16, 32, 64 bit)
- Floats (16, 32, 64 bit)
- RGBA8 Colors
- HexII
- Binary
- Decoding data as ASCII and custom encodings
- Built-in support for UTF-8, UTF-16, ShiftJIS, most Windows encodings and many more
- Paged data view
</details>
<details>
<summary><strong>Custom C++-like pattern language for parsing highlighting a file's content</strong></summary>
- Automatic loading based on MIME types and magic values
- Arrays, pointers, structs, unions, enums, bitfields, namespaces, little and big endian support, conditionals and much more!
- Goto from start, end and current cursor position
- Custom C++-like pattern language for parsing highlighting a file's content
- Automatic loading based on MIME type
- arrays, pointers, structs, unions, enums, bitfields, namespaces, little and big endian support, conditionals and much more!
- Useful error messages, syntax highlighting and error marking
- Support for visualizing many different types of data
- Images
- Audio
- 3D Models
- Coordinates
- Time stamps
</details>
<details>
<summary><strong>Theming support</strong></summary>
- Doesn't burn out your retinas when used in late-night sessions
- Dark mode by default, but a light mode is available as well
- Customizable colors and styles for all UI elements through shareable theme files
- Support for custom fonts
</details>
<details>
<summary><strong>Importing and Exporting data</strong></summary>
- Doesn't burn out your retinas when used in late-night sessions
- Dark mode by default, but a light mode is available as well
- Data importing
- Base64 files
- IPS and IPS32 patches
- Markdown reports
</details>
<details>
<summary><strong>Data Inspector</strong></summary>
- Interpreting data as many different types with endianess, decimal, hexadecimal and octal support and bit inversion
- Unsigned and signed integers (8, 16, 24, 32, 48, 64 bit)
- Floats (16, 32, 64 bit)
- Signed and Unsigned LEB128
- ASCII, Wide and UTF-8 characters and strings
- time32_t, time64_t, DOS date and time
- GUIDs
- RGBA8 and RGB65 Colors
- Copying and modifying bytes through the inspector
- Adding new data types through the pattern language
- Support for hiding rows that aren't used
</details>
<details>
<summary><strong>Node-based data pre-processor</strong></summary>
- Modify, decrypt and decode data before it's being displayed in the hex editor
- Modify data without touching the underlying source
- Support for adding custom nodes
</details>
<details>
<summary><strong>Loading data from many different data sources</strong></summary>
- Local Files
- Support for huge files with fast and efficient loading
- Raw Disks
- Loading data from raw disks and partitions
- GDB Server
- Access the RAM of a running process or embedded devices through GDB
- Intel Hex and Motorola SREC data
- Process Memory
- Inspect the entire address space of a running process
</details>
<details>
<summary><strong>Data searching</strong></summary>
- Support for searching the entire file or only a selection
- String extraction
- Option to specify minimum length and character set (lower case, upper case, digits, symbols)
- Option to specify encoding (ASCII, UTF-8, UTF-16 big and little endian)
- Sequence search
- Search for a sequence of bytes or characters
- Option to ignore character case
- Regex search
- Search for strings using regular expressions
- Binary Pattern
- Search for sequences of bytes with optional wildcards
- Numeric Value search
- Search for signed/unsigned integers and floats
- Search for ranges of values
- Option to specify size and endianess
- Option to ignore unaligned values
</details>
<details>
<summary><strong>Data hashing support</strong></summary>
- Many different algorithms available
- CRC8, CRC16 and CRC32 with custom initial values and polynomials
- Many default polynomials available
- MD5
- SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
- Adler32
- AP
- BKDR
- Bernstein, Bernstein1
- DEK, DJB, ELF, FNV1, FNV1a, JS, PJW, RS, SDBM
- OneAtTime, Rotating, ShiftAndXor, SuperFast
- Murmur2_32, MurmurHash3_x86_32, MurmurHash3_x86_128, MurmurHash3_x64_128
- SipHash64, SipHash128
- XXHash32, XXHash64
- Tiger, Tiger2
- Blake2B, Blake2S
- Hashing of specific regions of the loaded data
- Hashing of arbitrary strings
</details>
<details>
<summary><strong>Diffing support</strong></summary>
- Compare data of different data sources
- Difference highlighting
- Table view of differences
</details>
<details>
<summary><strong>Integrated disassembler</strong></summary>
- Support for all architectures supported by Capstone
- ARM32 (ARM, Thumb, Cortex-M, AArch32)
- ARM64
- MIPS (MIPS32, MIPS64, MIPS32R6, Micro)
- x86 (16-bit, 32-bit, 64-bit)
- PowerPC (32-bit, 64-bit)
- SPARC
- IBM SystemZ
- xCORE
- M68K
- TMS320C64X
- M680X
- Ethereum
- RISC-V
- WebAssembly
- MOS65XX
- Berkeley Packet Filter
</details>
<details>
<summary><strong>Bookmarks</strong></summary>
- Support for bookmarks with custom names and colors
- Highlighting of bookmarked region in the hex editor
- Jump to bookmarks
- Open content of bookmark in a new tab
- Add comments to bookmarks
</details>
<details>
<summary><strong>Featureful data analyzer and visualizer</strong></summary>
- Data exporting
- IPS and IPS32 patches
- Data inspector allowing interpretation of data as many different types (little and big endian)
- Huge file support with fast and efficient loading
- String search
- Copying of strings
- Copying of demangled strings
- File hashing support
- CRC16 and CRC32 with custom initial values and polynomials
- MD4, MD5
- SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
- Disassembler supporting many architectures (frontend for Capstone)
- ARM32 (ARM, Thumb, Cortex-M, AArch32)
- ARM64
- MIPS (MIPS32, MIPS64, MIPS32R6, Micro)
- x86 (16-bit, 32-bit, 64-bit)
- PowerPC (32-bit, 64-bit)
- SPARC
- IBM SystemZ
- xCORE
- M68K
- TMS320C64X
- M680X
- Ethereum
- RISC-V
- WebAssembly
- MOS65XX
- Berkeley Packet Filter
- Bookmarks
- Region highlighting
- Comments
- Data Analyzer
- File magic-based file parser and MIME type database
- Byte type distribution graph
- Byte distribution graph
- Entropy graph
- Highest and average entropy
- Encrypted / Compressed file detection
- Digram and Layered distribution graphs
</details>
<details>
<summary><strong>YARA Rule support</strong></summary>
- Scan a file for vulnerabilities with official yara rules
- Highlight matches in the hex editor
- Jump to matches
- Apply multiple rules at once
</details>
<details>
<summary><strong>Helpful tools</strong></summary>
- Itanium, MSVC, Rust and D-Lang demangler based on LLVM
- Built-in Content Store
- Download all files found in the database directly from within ImHex
- Yara Rules support
- Quickly scan a file for vulnerabilities with official yara rules
- Helpful tools
- Itanium and MSVC demangler
- ASCII table
- Regex replacer
- Mathematical expression evaluator (Calculator)
- Graphing calculator
- Hexadecimal Color picker with support for many different formats
- Hexadecimal Color picker
- Base converter
- Byte swapper
- UNIX Permissions calculator
- Wikipedia term definition finder
- File utilities
- File splitter
- File combiner
- File shredder
- IEEE754 Float visualizer
- Division by invariant multiplication calculator
- TCP Client/Server
- Euclidean algorithm calculator
</details>
<details>
<summary><strong>Built-in Content updater</strong></summary>
- Download all files found in the database directly from within ImHex
- Pattern files for decoding various file formats
- Libraries for the pattern language
- Magic files for file type detection
- Custom data processor nodes
- Custom encodings
- Custom themes
- Yara rules
</details>
<details>
<summary><strong>Modern Interface</strong></summary>
- Support for multiple workspaces
- Support for custom layouts
- Detachable windows
</details>
<details>
<summary><strong>Easy to get started</strong></summary>
- Support for many different languages
- Simplified mode for beginners
- Extensive documentation
- Many example files available on [the Database](https://github.com/WerWolv/ImHex-Patterns)
- Achievements guiding you through the features of ImHex
- Interactive tutorials
</details>
## Pattern Language
@@ -321,13 +148,7 @@ For format patterns, libraries, magic and constant files, check out the [ImHex-P
## Requirements
To use ImHex, the following minimal system requirements need to be met.
> [!IMPORTANT]
> ImHex requires a GPU with OpenGL 3.0 support in general.
> There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions.
>
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one (especially Intel HD GPUs are known to cause issues).
To use ImHex, the following minimal system requirements need to be met:
- **OS**:
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
@@ -354,9 +175,8 @@ To compile ImHex on any platform, GCC (or Clang) is required with a version that
On macOS, Clang is also required to compile some ObjC code.
All releases are being built using latest available GCC.
> [!NOTE]
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
> All dependencies that aren't bundled, can be installed using the dependency installer scripts found in the `/dist` folder.
Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
All dependencies that aren't bundled, can be installed using the dependency installer scripts found in the `/dist` folder.
For more information, check out the [Compiling](/dist/compiling) guide.
@@ -378,7 +198,7 @@ To develop plugins for ImHex, use one of the following two templates projects to
- [Roblabla](https://github.com/Roblabla) for adding MSI Installer support to ImHex
- [jam1garner](https://github.com/jam1garner) and [raytwo](https://github.com/raytwo) for their help with adding Rust support to plugins
- [Mailaender](https://github.com/Mailaender) for getting ImHex onto Flathub
- [iTrooz](https://github.com/iTrooz) for many improvements and new features to Imhex
- [iTrooz](https://github.com/iTrooz) for many improvements related to release packaging and the GitHub Action runners.
- Everybody else who has reported issues on Discord or GitHub that I had great conversations with :)
### Dependencies

View File

@@ -7,4 +7,4 @@ If you built ImHex yourself and experience issues that are not present in the ve
## Reporting a Vulnerability
Any critical vulnerabilities can be reported through Discord (@werwolv).
Any critical vulnerabilities can be reported through Discord @WerWolv#1337

View File

@@ -1 +1 @@
1.32.1
1.31.0

View File

@@ -89,6 +89,14 @@ endmacro()
macro(configurePackingResources)
set(IMHEX_FORCE_LINK_PLUGINS "")
option (CREATE_PACKAGE "Create a package with CPack" OFF)
if (APPLE)
option (CREATE_BUNDLE "Create a bundle on macOS" OFF)
endif()
if (WIN32)
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
set(APPLICATION_TYPE WIN32)
@@ -96,7 +104,7 @@ macro(configurePackingResources)
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/resource.rc")
if (IMHEX_GENERATE_PACKAGE)
if (CREATE_PACKAGE)
set(CPACK_GENERATOR "WIX")
set(CPACK_PACKAGE_NAME "ImHex")
set(CPACK_PACKAGE_VENDOR "WerWolv")
@@ -108,13 +116,13 @@ macro(configurePackingResources)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
)
)
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/resources/dist/windows/LICENSE.rtf")
endif()
elseif (APPLE)
set (IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns")
if (IMHEX_GENERATE_PACKAGE)
if (CREATE_BUNDLE)
set(APPLICATION_TYPE MACOSX_BUNDLE)
set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns")
@@ -129,9 +137,9 @@ macro(configurePackingResources)
string(TIMESTAMP CURR_YEAR "%Y")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 - ${CURR_YEAR} WerWolv. All rights reserved." )
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode")
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/imhex.app")
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/ImHex.app")
else ()
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/imhex.app")
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/ImHex.app")
endif()
set(PLUGINS_INSTALL_LOCATION "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
@@ -147,28 +155,30 @@ macro(createPackage)
foreach (plugin IN LISTS PLUGINS)
add_subdirectory("plugins/${plugin}")
if (TARGET ${plugin})
get_target_property(IS_RUST_PROJECT ${plugin} RUST_PROJECT)
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
if (APPLE)
if (IMHEX_GENERATE_PACKAGE)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
else ()
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
endif ()
if (IS_RUST_PROJECT)
set_target_properties(${plugin} PROPERTIES CARGO_BUILD_TARGET_DIR ${CMAKE_BINARY_DIR}/plugins)
get_target_property(PLUGIN_LOCATION ${plugin} LOCATION)
install(FILES "${PLUGIN_LOCATION}/../${plugin}.hexplug" DESTINATION "${PLUGINS_INSTALL_LOCATION}" PERMISSIONS ${LIBRARY_PERMISSIONS})
else ()
if (WIN32)
get_target_property(target_type ${plugin} TYPE)
if (target_type STREQUAL "SHARED_LIBRARY")
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})
elseif (APPLE)
if (CREATE_BUNDLE)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
else ()
install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION})
endif()
else()
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
endif ()
else ()
install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION})
endif()
endif()
endif ()
endif ()
add_dependencies(imhex_all ${plugin})
endif ()
@@ -180,17 +190,12 @@ macro(createPackage)
# Install binaries directly in the prefix, usually C:\Program Files\ImHex.
set(CMAKE_INSTALL_BINDIR ".")
set(PLUGIN_TARGET_FILES "")
foreach (plugin IN LISTS PLUGINS)
list(APPEND PLUGIN_TARGET_FILES "$<TARGET_FILE:${plugin}>")
endforeach ()
# Grab all dynamically linked dependencies.
install(CODE "set(CMAKE_INSTALL_BINDIR \"${CMAKE_INSTALL_BINDIR}\")")
install(CODE "set(PLUGIN_TARGET_FILES \"${PLUGIN_TARGET_FILES}\")")
INSTALL(CODE "set(CMAKE_INSTALL_BINDIR \"${CMAKE_INSTALL_BINDIR}\")")
INSTALL(CODE "LIST(APPEND DEP_FOLDERS \${PY_PARENT})")
install(CODE [[
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${PLUGIN_TARGET_FILES} $<TARGET_FILE:libimhex> $<TARGET_FILE:main>
EXECUTABLES $<TARGET_FILE:builtin> $<TARGET_FILE:libimhex> $<TARGET_FILE:main>
RESOLVED_DEPENDENCIES_VAR _r_deps
UNRESOLVED_DEPENDENCIES_VAR _u_deps
CONFLICTING_DEPENDENCIES_PREFIX _c_deps
@@ -217,27 +222,27 @@ macro(createPackage)
elseif(UNIX AND NOT APPLE)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${LIBRARY_PERMISSIONS})
downloadImHexPatternsFiles("./share/imhex")
# install AppStream file
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/net.werwolv.imhex.metainfo.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
# install symlink for the old standard name
file(CREATE_LINK net.werwolv.imhex.metainfo.xml ${CMAKE_CURRENT_BINARY_DIR}/net.werwolv.imhex.appdata.xml SYMBOLIC)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/net.werwolv.imhex.appdata.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
endif()
if (IMHEX_GENERATE_PACKAGE AND APPLE)
if (CREATE_BUNDLE)
include(PostprocessBundle)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
@@ -250,7 +255,7 @@ macro(createPackage)
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
downloadImHexPatternsFiles("${IMHEX_BUNDLE_PATH}/Contents/MacOS")
install(FILES ${IMHEX_ICON} DESTINATION "${IMHEX_BUNDLE_PATH}/Contents/Resources")
install(TARGETS main BUNDLE DESTINATION ".")
install(FILES $<TARGET_FILE:main> DESTINATION "${IMHEX_BUNDLE_PATH}")
@@ -260,9 +265,6 @@ macro(createPackage)
# Enforce DragNDrop packaging.
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/resources/dist/macos/AppIcon.icns" )
set(CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/imhex.app/Contents/Info.plist")
else()
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(WIN32) # Forwarder is only needed on Windows
@@ -270,8 +272,10 @@ macro(createPackage)
endif()
endif()
if (IMHEX_GENERATE_PACKAGE)
if (CREATE_PACKAGE)
set (CPACK_BUNDLE_NAME "ImHex")
set (CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/resources/dist/macos/AppIcon.icns" )
set (CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/ImHex.app/Contents/Info.plist")
include(CPack)
endif()
@@ -293,6 +297,10 @@ macro(configureCMake)
# Enable C and C++ languages
enable_language(C CXX)
if (CMAKE_CROSSCOMPILING)
message(STATUS "ImHex is being Cross-Compiled for ${CMAKE_SYSTEM_NAME}!")
endif ()
# Configure use of recommended build tools
if (IMHEX_USE_DEFAULT_BUILD_SETTINGS)
message(STATUS "Configuring CMake to use recommended build tools...")
@@ -376,7 +384,7 @@ function(detectBadClone)
return()
endif()
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*")
file (GLOB EXTERNAL_DIRS "lib/external/*")
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
list(LENGTH RESULT ENTRY_COUNT)
@@ -400,35 +408,6 @@ function(verifyCompiler)
endif()
endfunction()
macro(detectBundledPlugins)
file(GLOB PLUGINS_DIRS "plugins/*")
if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
if (NOT (${PLUGIN_NAME} IN_LIST IMHEX_EXCLUDE_PLUGINS))
list(APPEND PLUGINS ${PLUGIN_NAME})
endif ()
endif()
endforeach()
else()
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
endif()
foreach(PLUGIN_NAME ${PLUGINS})
message(STATUS "Enabled bundled plugin '${PLUGIN_NAME}'")
endforeach()
if (NOT PLUGINS)
message(FATAL_ERROR "No bundled plugins enabled")
endif()
if (NOT ("builtin" IN_LIST PLUGINS))
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
endif ()
endmacro()
macro(setVariableInParent variable value)
get_directory_property(hasParent PARENT_DIRECTORY)
@@ -448,9 +427,9 @@ function(downloadImHexPatternsFiles dest)
endif ()
FetchContent_Declare(
imhex_patterns
GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git
GIT_TAG origin/master
imhex_patterns
GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git
GIT_TAG origin/master
)
message(STATUS "Downloading ImHex-Patterns repo branch ${PATTERNS_BRANCH}...")
@@ -473,40 +452,23 @@ endfunction()
macro(setupCompilerFlags target)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Define strict compilation flags
if (IMHEX_STRICT_WARNINGS)
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wall -Wextra -Wpedantic -Werror")
endif()
if (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -rdynamic")
set(IMHEX_COMMON_FLAGS "-Wall -Wextra -Wpedantic -Werror")
endif()
set(IMHEX_C_FLAGS "${IMHEX_COMMON_FLAGS} -Wno-array-bounds -Wno-deprecated-declarations")
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
# Disable some warnings
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations")
if (IMHEX_ENABLE_UNITY_BUILD AND WIN32)
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wa,-mbig-obj")
endif ()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_C_FLAGS "${IMHEX_C_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
endif()
endif()
# Disable some warnings for gcc
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
endif()
# Define emscripten-specific disabled warnings
if (EMSCRIPTEN)
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
set(IMHEX_C_FLAGS "${IMHEX_C_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
endif ()
# Set actual CMake flags
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS} ${IMHEX_CXX_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_CXX_FLAGS} ${IMHEX_C_FLAGS}")
set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
endmacro()
@@ -514,43 +476,42 @@ endmacro()
macro(setUninstallTarget)
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
endmacro()
macro(addBundledLibraries)
find_package(PkgConfig REQUIRED)
set(EXTERNAL_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
set(THIRD_PARTY_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/third_party")
set(EXTERN_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/imgui)
add_subdirectory(${EXTERN_LIBS_FOLDER}/imgui)
set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL)
set_target_properties(microtar PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL)
set_property(TARGET libwolv-types PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-utils PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-io PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-hash PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-containers PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-net PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-math_eval PROPERTY POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${EXTERN_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL)
set_property(TARGET libwolv-types PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-utils PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-io PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-hash PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-containers PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-net PROPERTY POSITION_INDEPENDENT_CODE ON)
set(XDGPP_INCLUDE_DIRS "${THIRD_PARTY_LIBS_FOLDER}/xdgpp")
set(XDGPP_INCLUDE_DIRS "${EXTERN_LIBS_FOLDER}/xdgpp")
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
find_package(PkgConfig REQUIRED)
if(NOT USE_SYSTEM_FMT)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(FMT_LIBRARIES fmt::fmt-header-only)
else()
@@ -571,7 +532,7 @@ macro(addBundledLibraries)
# nfd
if (NOT USE_SYSTEM_NFD)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/nativefiledialog EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/nativefiledialog EXCLUDE_FROM_ALL)
set_target_properties(nfd PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(NFD_LIBRARIES nfd)
else()
@@ -581,7 +542,7 @@ macro(addBundledLibraries)
endif()
if(NOT USE_SYSTEM_NLOHMANN_JSON)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/nlohmann_json EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/nlohmann_json EXCLUDE_FROM_ALL)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
else()
find_package(nlohmann_json 3.10.2 REQUIRED)
@@ -589,14 +550,32 @@ macro(addBundledLibraries)
endif()
if (NOT USE_SYSTEM_LLVM)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL)
set_target_properties(LLVMDemangle PROPERTIES POSITION_INDEPENDENT_CODE ON)
else()
find_package(LLVM REQUIRED Demangle)
endif()
if (NOT USE_SYSTEM_YARA)
add_subdirectory(${EXTERN_LIBS_FOLDER}/yara EXCLUDE_FROM_ALL)
set_target_properties(libyara PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(YARA_LIBRARIES libyara)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(YARA REQUIRED IMPORTED_TARGET yara)
endif()
if (NOT USE_SYSTEM_MINIAUDIO)
add_subdirectory(${EXTERN_LIBS_FOLDER}/miniaudio EXCLUDE_FROM_ALL)
set_target_properties(miniaudio PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(MINIAUDIO_LIBRARIES miniaudio)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(miniaudio REQUIRED IMPORTED_TARGET miniaudio)
endif()
if (NOT USE_SYSTEM_JTHREAD)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL)
set(JTHREAD_LIBRARIES jthread)
else()
find_path(JOSUTTIS_JTHREAD_INCLUDE_DIRS "condition_variable_any2.hpp")
@@ -607,8 +586,22 @@ macro(addBundledLibraries)
set(JTHREAD_LIBRARIES jthread)
endif()
if (NOT USE_SYSTEM_CAPSTONE)
set(CAPSTONE_BUILD_STATIC_RUNTIME OFF CACHE BOOL "Disable shared library building")
set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "Disable shared library building")
set(CAPSTONE_BUILD_TESTS OFF CACHE BOOL "Disable tests")
add_subdirectory(${EXTERN_LIBS_FOLDER}/capstone EXCLUDE_FROM_ALL)
set_target_properties(capstone PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_compile_options(capstone PRIVATE -Wno-unused-function)
set(CAPSTONE_LIBRARIES "capstone")
set(CAPSTONE_INCLUDE_DIRS ${EXTERN_LIBS_FOLDER}/capstone/include)
else()
find_package(PkgConfig REQUIRED)
pkg_search_module(CAPSTONE 4.0.2 REQUIRED capstone)
endif()
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF)
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERN_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
set_target_properties(libpl PROPERTIES POSITION_INDEPENDENT_CODE ON)
find_package(mbedTLS 3.4.0 REQUIRED)
@@ -645,12 +638,6 @@ macro(addBundledLibraries)
endif ()
endmacro()
function(enableUnityBuild TARGET)
if (IMHEX_ENABLE_UNITY_BUILD)
set_target_properties(${TARGET} PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE BATCH)
endif ()
endfunction()
function(generatePDBs)
if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
return()
@@ -680,11 +667,9 @@ function(generatePDBs)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
WORKING_DIRECTORY ${cv2pdb_SOURCE_DIR}
COMMAND
(
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe
$<TARGET_FILE:${PDB}>
) || (exit 0)
(${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe
$<TARGET_FILE:${PDB}>) || (exit 0)
DEPENDS $<TARGET_FILE:${PDB}>
COMMAND_EXPAND_LISTS)
@@ -695,33 +680,10 @@ function(generatePDBs)
endfunction()
function(generateSDKDirectory)
if (WIN32)
set(SDK_PATH "./sdk")
elseif (APPLE)
set(SDK_PATH "imhex.app/Contents/Resources/sdk")
else()
set(SDK_PATH "share/imhex/sdk")
endif()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/external DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/imgui DESTINATION "${SDK_PATH}/lib/third_party")
if (NOT USE_SYSTEM_FMT)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/fmt DESTINATION "${SDK_PATH}/lib/third_party")
endif()
if (NOT USE_SYSTEM_NLOHMANN_JSON)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party")
endif()
set(SDK_PATH "./sdk")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex/include DESTINATION "${SDK_PATH}")
install(FILES ${CMAKE_SOURCE_DIR}/cmake/modules/ImHexPlugin.cmake DESTINATION "${SDK_PATH}/cmake/modules")
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
install(FILES ${CMAKE_SOURCE_DIR}/cmake/sdk/CMakeLists.txt DESTINATION "${SDK_PATH}")
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
install(TARGETS libimhex RUNTIME DESTINATION "${SDK_PATH}/lib")
install(TARGETS libimhex LIBRARY DESTINATION "${SDK_PATH}/lib")
endfunction()
function(addIncludesFromLibrary target library)
get_target_property(library_include_dirs ${library} INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(${target} PRIVATE ${library_include_dirs})
endfunction()

View File

@@ -16,7 +16,7 @@ if (NOT DOTNET_EXECUTABLE)
set(DOTNET_EXECUTABLE dotnet)
endif ()
set(CORECLR_VERSION "8.0")
set(CORECLR_VERSION "7.0")
execute_process(COMMAND ${DOTNET_EXECUTABLE} "--list-runtimes" OUTPUT_VARIABLE CORECLR_LIST_RUNTIMES_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE)
if (CORECLR_LIST_RUNTIMES_OUTPUT STREQUAL "")
@@ -75,7 +75,7 @@ find_file(CoreClrEmbed_SHARED_LIBRARY nethost.dll nethost.so libnethost.so netho
if (CoreClrEmbed_INCLUDE_DIR AND CoreClrEmbed_LIBRARY)
set(CoreClrEmbed_FOUND TRUE)
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}" CACHE STRING "CoreClrEmbed libraries" FORCE)
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}" CACHE STRING "CoreClrEmbed shared libraries" FORCE)
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}" CACHE STRING "CoreClrEmbed include directories" FORCE)
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}")
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}")
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}")
endif()

View File

@@ -1,6 +1,6 @@
macro(add_imhex_plugin)
# Parse arguments
set(options LIBRARY_PLUGIN)
set(options "")
set(oneValueArgs NAME)
set(multiValueArgs SOURCES INCLUDES LIBRARIES)
cmake_parse_arguments(IMHEX_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -12,15 +12,8 @@ macro(add_imhex_plugin)
configure_file(${CMAKE_SOURCE_DIR}/dist/web/plugin-bundle.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/plugin-bundle.cpp @ONLY)
target_sources(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/plugin-bundle.cpp)
set(IMHEX_PLUGIN_SUFFIX ".hexplug")
else()
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
set(IMHEX_PLUGIN_LIBRARY_TYPE SHARED)
set(IMHEX_PLUGIN_SUFFIX ".hexpluglib")
else()
set(IMHEX_PLUGIN_LIBRARY_TYPE MODULE)
set(IMHEX_PLUGIN_SUFFIX ".hexplug")
endif()
set(IMHEX_PLUGIN_LIBRARY_TYPE SHARED)
endif()
# Define new project for plugin
@@ -31,8 +24,7 @@ macro(add_imhex_plugin)
# Add include directories and link libraries
target_include_directories(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_INCLUDES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${IMHEX_PLUGIN_LIBRARIES} ${FMT_LIBRARIES} imgui_all_includes libwolv)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl)
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} ${IMHEX_PLUGIN_LIBRARIES})
# Add IMHEX_PROJECT_NAME and IMHEX_VERSION define
target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}")
@@ -41,7 +33,6 @@ macro(add_imhex_plugin)
# Enable required compiler flags
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
enableUnityBuild(${IMHEX_PLUGIN_NAME})
setupCompilerFlags(${IMHEX_PLUGIN_NAME})
# Configure build properties
@@ -50,7 +41,7 @@ macro(add_imhex_plugin)
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
CXX_STANDARD 23
PREFIX ""
SUFFIX ${IMHEX_PLUGIN_SUFFIX}
SUFFIX ".hexplug"
)
# Setup a romfs for the plugin
@@ -61,9 +52,7 @@ macro(add_imhex_plugin)
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
# Add the new plugin to the main dependency list so it gets built by default
if (TARGET imhex_all)
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
endif()
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
endmacro()
macro(add_romfs_resource input output)

View File

@@ -24,38 +24,31 @@ if(CMAKE_GENERATOR)
return()
endif()
# IMHEX PATCH BEGIN
# The function defined above doesn't keep in mind that if we are cross-compiling to MacOS, APPLE must be 1,
# so we force it here (where else would this script be run anyway ? This seems to be MacOS-specific code)
SET(APPLE 1)
# IMHEX PATCHE END
get_filename_component(BUNDLE_PATH "${BUNDLE_PATH}" ABSOLUTE)
message(STATUS "Fixing up application bundle: ${BUNDLE_PATH}")
# Make sure to fix up any included ImHex plugin.
file(GLOB_RECURSE plugins "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug")
file(GLOB_RECURSE plugin_libs "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexpluglib")
file(GLOB_RECURSE extra_libs "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug")
# BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which
# makes it sometimes break on libraries that do weird things with @rpath. Specify
# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625
# is fixed and in our minimum CMake version.
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS} "${BUNDLE_PATH}/Contents/MacOS/plugins")
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS})
message(STATUS "Fixing up application bundle: ${extra_dirs}")
# BundleUtilities is overly verbose, so disable most of its messages
#function(message)
# if(NOT ARGV MATCHES "^STATUS;")
# _message(${ARGV})
# endif()
#endfunction()
function(message)
if(NOT ARGV MATCHES "^STATUS;")
_message(${ARGV})
endif()
endfunction()
include(BundleUtilities)
set(BU_CHMOD_BUNDLE_ITEMS ON)
fixup_bundle("${BUNDLE_PATH}" "${plugins};${plugin_libs}" "${extra_dirs}")
fixup_bundle("${BUNDLE_PATH}" "${extra_libs}" "${extra_dirs}")
if (CODE_SIGN_CERTIFICATE_ID)
# Hack around Apple Silicon signing bugs by copying the real app, signing it and moving it back.

View File

@@ -1,43 +0,0 @@
cmake_minimum_required(VERSION 3.20)
project(ImHexSDK)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_helpers.cmake")
set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
include(ImHexPlugin)
function(add_subdirectory_if_exists folder)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${folder}/CMakeLists.txt")
add_subdirectory("${folder}")
endif()
endfunction()
set(IMHEX_EXTERNAL_PLUGIN_BUILD ON)
add_custom_target(imhex_all)
add_subdirectory(lib/third_party/imgui)
add_subdirectory_if_exists(lib/third_party/fmt)
add_subdirectory_if_exists(lib/third_party/nlohmann_json)
add_subdirectory(lib/external/libwolv)
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF)
add_subdirectory(lib/external/pattern_language)
add_subdirectory(lib/libimhex)
if (WIN32)
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex.dll"
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/liblibimhex.dll.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
elseif (APPLE)
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex.dylib"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
else()
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex.so"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
endif()

4
dist/Arch/PKGBUILD vendored
View File

@@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
arch=("x86_64")
url="https://github.com/WerWolv/ImHex"
license=('GPL2')
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json libarchive)
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json)
makedepends=(git)
provides=(imhex)
conflicts=(imhex)
@@ -19,7 +19,7 @@ package() {
install -Dm755 "$srcdir/usr/bin/imhex" "$pkgdir/usr/bin/imhex"
install -Dm644 "$srcdir/usr/lib/libimhex.so.$pkgver" "$pkgdir/usr/lib/libimhex.so.$pkgver"
for plugin in "$srcdir/usr/lib/imhex/plugins/"*.hexplug*; do
for plugin in "$srcdir/usr/lib/imhex/plugins/"*.hexplug; do
install -Dm644 "$plugin" "$pkgdir/usr/lib/imhex/plugins/${plugin##*/}"
done

3
dist/Brewfile vendored
View File

@@ -9,5 +9,4 @@ brew "curl"
brew "gcc@12"
brew "llvm"
brew "glfw"
brew "ninja"
brew "libarchive"
brew "ninja"

View File

@@ -4,7 +4,7 @@ Section: editors
Priority: optional
Architecture: amd64
License: GNU GPL-2
Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libarchive13
Depends: libglfw3, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
Maintainer: WerWolv <hey@werwolv.net>
Description: ImHex Hex Editor
A Hex Editor for Reverse Engineers, Programmers and

View File

@@ -24,6 +24,5 @@ RDEPEND="${DEPEND}
dev-cpp/nlohmann_json
dbus
xdg-desktop-portal
app-arch/libarchive
"
BDEPEND="${DEPEND}"

View File

@@ -1,48 +0,0 @@
For a TLDR of commands see [How to build](#How-to-build)
# Introduction
The original CI we used (vanilla Github Actions) was great for specifying what steps to execute to build packages. It could even do some custom steps with reusable actions. But it had problem: no local reproducibility. This meant that:
- We couldn't test code properly locally, we were dependent on GitHub to do it
- If something was wrong and we had to debug the build script, it was *long and painful* because we had to wait for Github runners to finish builds, and couldn't quickly iterate
To solve this, we are now trying to move the CI build script to docker containers (so using Dockerfiles)
# How to build
Commands are available in the [CI](../../.github/workflows/build.yml) and you should prefer copying them from there.
But here is a general command that should work for every build we have:
```
docker buildx build . -f <DOCKERFILE_PATH> --progress plain --build-arg 'JOBS=4' --build-arg 'BUILD_TYPE=Debug' --build-context imhex=$(pwd) --output local
```
where `<DOCKERFILE_PATH>` should be replaced by the wanted Dockerfile base d on the build you want to do:
| Wanted build | Dockerfile path |
|--------------|-----------------------------|
| MacOS M1 | dist/macOS/arm64.Dockerfile |
| AppImage | dist/appimage/Dockerfile |
| Web version | dist/web/Dockerfile |
We'll explain this command in the next section
# Useful knowledge about Docker builds
Docker-based builds work with a Dockerfile. You run the Dockerfile, it builds the package.
We are using a base environment (often given to us by dockerhub) (e.g. ubuntu:22.04) which is really just a root filesystem, and we then run shell commands in that env, just like a shell script
Docker-based builds have two kind of caches used:
- layer cache, which mean that if a layer (instruction) hasn't been changed, and previous layers haven't changed, it will not be run again
- a `COPY` layer will be invalidated if one of the file copied has changed
- mount cache, which are per-instructions mounts that will be cached and restored in the next run. Mounts on different folders will not collide
Docker cache tends to grow very quickly when constantly making changes in the Dockerfile and rebuilding (a.k.a debugging what's going on), you can clear it with something like `docker system prune -a`
In the command saw earlier:
- `.` is the base folder that the Dockerfile will be allowed to see
- `-f <path>` is to specify the Dockerfile path
- `--progress plain` is to allow you to see the output of instructions
- `--build-arg <key>=<value>` is to allow to to specify arguments to the build (like -DKEY=VALUE in CMake)
- `--build-context key=<folder>` is to specify folders other than the base folder that the Dockerfile is allowed to see
- `--output <path>` is the path to write the output package to. If not specified, Docker will create an image as the output (probably not what you want)

View File

@@ -17,7 +17,8 @@ PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/p
MACOSX_DEPLOYMENT_TARGET="10.15" \
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DIMHEX_GENERATE_PACKAGE=ON \
-DCREATE_BUNDLE=ON \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \

View File

@@ -1,18 +1,17 @@
#!/usr/bin/env sh
pacman -S $@ --needed \
cmake \
gcc \
lld \
glfw \
file \
mbedtls \
freetype2 \
dbus \
gtk3 \
curl \
fmt \
yara \
cmake \
gcc \
lld \
glfw \
file \
mbedtls \
freetype2 \
dbus \
gtk3 \
curl \
fmt \
yara \
nlohmann-json \
ninja \
libarchive
ninja

View File

@@ -22,5 +22,4 @@ apt install -y \
libdbus-1-dev \
libcurl4-gnutls-dev \
libgtk-3-dev \
ninja-build \
libarchive-dev
ninja-build

View File

@@ -12,5 +12,4 @@ dnf install -y \
glfw-devel \
lld \
mbedtls-devel \
gtk3-devel \
libarchive-devel
gtk3-devel

View File

@@ -12,5 +12,4 @@ pacman -S --needed --noconfirm \
mingw-w64-x86_64-freetype \
mingw-w64-x86_64-dlfcn \
mingw-w64-x86_64-ninja \
mingw-w64-x86_64-capstone \
mingw-w64-x86_64-libarchive
mingw-w64-x86_64-capstone

View File

@@ -1,166 +0,0 @@
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
ENV MACOSX_DEPLOYMENT_TARGET 12.1
# -- DOWNLOADING STUFF
## Install make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
## fix environment
### add install_name_tool for cmake command that won't have the right env set (see PostprocessBundle.cmake function postprocess_bundle())
RUN cp /osxcross/build/cctools-port/cctools/misc/install_name_tool /usr/bin/install_name_tool
### a cmake thing wants 'otool' and not '' apparently
RUN cp /osxcross/target/bin/aarch64-apple-darwin23-otool /usr/bin/otool
## Clone glfw
RUN <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
git clone https://github.com/glfw/glfw /mnt/glfw
fi
EOF
RUN --mount=type=cache,target=/cache <<EOF
## Download SDK is missing (it may have been removed from the image)
set -xe
if [ ! -d /osxcross/target/SDK/MacOSX14.0.sdk ]; then
wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
mkdir -p /osxcross/target/SDK
tar -C /osxcross/target/SDK -xf /cache/MacOSX14.0.sdk.tar.xz
fi
EOF
## Download libmagic
### Clone libmagic
RUN git clone https://github.com/file/file /mnt/file
### Download libmagic dependencies
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt install -y libtool autoconf
# -- DOWNLOADING + BUILDING STUFF
ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
RUN --mount=type=cache,target=/cache <<EOF
## Install dependencies with vcpkg
set -xe
mkdir -p $VCPKG_DEFAULT_BINARY_CACHE
vcpkg install --triplet=arm-osx-mytriplet curl
vcpkg install --triplet=arm-osx-mytriplet mbedtls
vcpkg install --triplet=arm-osx-mytriplet freetype
vcpkg install --triplet=arm-osx-mytriplet josuttis-jthread
vcpkg install --triplet=arm-osx-mytriplet libarchive
EOF
## Install glfw3 dep
ARG CUSTOM_GLFW
RUN --mount=type=cache,target=/cache <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
echo "Flag confirmation: using custom GLFW for software rendering"
else
echo "Flag confirmation: using system GLFW"
vcpkg install --triplet=arm-osx-mytriplet glfw3
fi
EOF
# -- BUILDING STUFF
ARG JOBS 1
ARG BUILD_TYPE Debug
## Build libmagic
RUN --mount=type=cache,target=/cache <<EOF
ccache -zs
set -xe
cd /mnt/file
autoreconf -is
# when cross-compiling, libmagic needs to have an the same version installed in the system.
# So we install it normally first
./configure --prefix /usr
make -j $JOBS install
# Now, we cross-compile it and install it in the libraries folder
CC=/osxcross/target/bin/aarch64-apple-darwin23-clang CXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
make -j $JOBS
make install
ccache -s
EOF
## Patch glfw
COPY --from=imhex /dist/macOS/0001-glfw-SW.patch /tmp
RUN <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
cd /mnt/glfw
git apply /tmp/0001-glfw-SW.patch
fi
EOF
## Build glfw
RUN --mount=type=cache,target=/cache <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
ccache -zs
cd /mnt/glfw
mkdir build
cd build
CC=o64-gcc CXX=o64-g++ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
..
ninja -j $JOBS install
ccache -s
fi
EOF
# Build ImHex
## Copy ImHex
COPY --from=imhex / /mnt/ImHex
## Patch ImHex with hacks
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
# Configure ImHex build
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
cd /mnt/ImHex && \
# compilers
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin23-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ \
cmake -G "Ninja" \
`# ccache flags` \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
`# MacOS cross-compiling flags` \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \
`# Override compilers for code generators` \
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
`# Normal ImHex flags` \
-DIMHEX_GENERATE_PACKAGE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
`# other flags` \
-DIMHEX_STRICT_WARNINGS=OFF \
-B build
## Build ImHex
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF
ccache -zs
set -xe
cd /mnt/ImHex
cmake --build build --parallel $JOBS
ccache -s
EOF
FROM scratch
COPY --from=build /mnt/ImHex/build/imhex.app imhex.app

View File

@@ -1,96 +0,0 @@
# This image is is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
FROM ubuntu:22.04
ENV PATH $PATH:/osxcross/target/bin
ENV LD_LIBRARY_PATH /osxcross/target/lib
ENV OSXCROSS_SDK /osxcross/target/SDK/MacOSX14.0.sdk
ENV OSXCROSS_TARGET darwin23
ENV OSXCROSS_TARGET_DIR /osxcross/target
ENV OSXCROSS_HOST aarch64-apple-darwin23
# -- DOWNLOADING STUFF
# Install common stuff
RUN --mount=type=cache,target=/var/lib/apt/lists/ export DEBIAN_FRONTEND=noninteractive &&\
export TZ=Etc/UTC &&\
dpkg --add-architecture i386 &&\
apt update &&\
apt -y install lsb-release build-essential python3 python3-pip git wget zip unzip pkg-config curl ninja-build software-properties-common gnupg libssl-dev ccache
# Install clang 17
RUN --mount=type=cache,target=/var/lib/apt/lists/ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 17 &&\
ln -s /usr/bin/clang-17 /usr/bin/clang &&\
ln -s /usr/bin/clang++-17 /usr/bin/clang++
# Install vcpkg
RUN cd / &&\
git clone --depth 1 https://github.com/Microsoft/vcpkg.git vcpkg &&\
cd /vcpkg &&\
./bootstrap-vcpkg.sh -disableMetrics &&\
ln -s /vcpkg/vcpkg /usr/bin/ &&\
vcpkg install vcpkg-cmake &&\
ln -s /vcpkg/downloads/tools/cmake-*/cmake-*/bin/cmake /usr/bin/
RUN --mount=type=cache,target=/cache <<EOF
## Clone osxcross
set -xe
git clone https://github.com/tpoechtrager/osxcross /cache/osxcross || true
cd /cache/osxcross
git pull
cp -r /cache/osxcross /osxcross
EOF
RUN --mount=type=cache,target=/cache <<EOF
## Download SDK
set -xe
wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
cp /cache/MacOSX14.0.sdk.tar.xz /osxcross/tarballs
EOF
# Init stuff
## setup ccache dir
ENV CCACHE_DIR /cache/ccache
# Install triplet file
COPY arm-osx-mytriplet.cmake /vcpkg/triplets/community
# -- BUILDING STUFF
ARG JOBS 1
# Install osxcross
## Build cross-compiler clang-17
RUN --mount=type=cache,target=/cache <<EOF
set -xe
ccache -zs
cd /osxcross
UNATTENDED=1 CC=/usr/lib/ccache/clang-17 CXX=/usr/lib/ccache/clang++-17 ./build.sh
ccache -s
EOF
# Not needed, because we don't use gcc for cross-compiling anymore
# ## Install dependencies for gcc-13
# RUN apt install -y gcc g++ zlib1g-dev libmpc-dev libmpfr-dev libgmp-dev
# ## Build cross-compiler gcc-13
# RUN --mount=type=cache,target=/cache <<EOF
# set -xe
# ccache -zs
# cd /osxcross
# UNATTENDED=1 CC=/usr/lib/ccache/gcc CXX=/usr/lib/ccache/g++ GCC_VERSION=13.2.0 ./build_gcc.sh
# ccache -s
# EOF
ARG DELETE_SDK=1
RUN <<EOF
# Conditionally delete the SDK from the image
set -xe
if [ "$DELETE_SDK" ]; then
rm -r /osxcross/target/SDK
echo "Deleted the SDK from the image"
else
echo "NOT deleting the SDK from the image"
fi
EOF

4
dist/macOS/macos_arm_toolchain.cmake vendored Normal file
View File

@@ -0,0 +1,4 @@
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm64)
set(CMAKE_OSX_ARCHITECTURES arm64 CACHE INTERNAL "" FORCE)
SET(CMAKE_OSX_SYSROOT macosx CACHE INTERNAL "" FORCE)

3
dist/msys2/PKGBUILD vendored
View File

@@ -16,8 +16,7 @@ makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
"${MINGW_PACKAGE_PREFIX}-file"
"${MINGW_PACKAGE_PREFIX}-mbedtls"
"${MINGW_PACKAGE_PREFIX}-polly"
"${MINGW_PACKAGE_PREFIX}-freetype"
"${MINGW_PACKAGE_PREFIX}-libarchive")
"${MINGW_PACKAGE_PREFIX}-freetype")
source=()
sha256sums=()

View File

@@ -12,10 +12,49 @@ finish-args:
- --device=all
modules:
- name: imhex
buildsystem: cmake
- name: libiconv
sources:
- type: archive
url: https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz
sha256: e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04
- name: glfw
buildsystem: cmake-ninja
builddir: true
config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_SHARED_LIBS:BOOL=ON
sources:
- type: archive
url: https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.zip
sha256: 08a33a512f29d7dbf78eab39bd7858576adcc95228c9efe8e4bc5f0f3261efc7
cleanup:
- /include
- /lib/pkgconfig
- name: mbedtls
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_C_FLAGS=-fPIC
sources:
- type: archive
url: https://github.com/ARMmbed/mbedtls/archive/refs/tags/v2.27.0.tar.gz
sha256: 2a07856e541f0e5f6eaee4f78018c52f25bd244ed76f9020dea54a8b02cac6ea
- name: nlohmann-json
buildsystem: cmake-ninja
builddir: true
config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_TESTING=OFF
sources:
- type: archive
url: https://github.com/nlohmann/json/archive/v3.9.1.tar.gz
sha256: 4cf0df69731494668bdd6460ed8cb269b68de9c19ad8c27abc24cd72605b2d5b
- name: imhex
buildsystem: cmake
sources:
- type: git

13
dist/rpm/imhex.spec vendored
View File

@@ -27,7 +27,6 @@ BuildRequires: mbedtls-devel
BuildRequires: yara-devel
BuildRequires: nativefiledialog-extended-devel
BuildRequires: dotnet-sdk-7.0
BuildRequires: libarchive-devel
%if 0%{?rhel}
BuildRequires: gcc-toolset-12
%endif
@@ -62,7 +61,7 @@ same time ImHex is completely free and open source under the GPLv2 language.
%prep
%autosetup -n ImHex
# remove bundled libs we aren't using
rm -rf lib/third_party/{fmt,nlohmann_json,yara}
rm -rf lib/external/{curl,fmt,llvm,nlohmann_json,yara}
%build
%if 0%{?rhel}
@@ -110,11 +109,11 @@ rm -f %{buildroot}%{_metainfodir}/net.werwolv.%{name}.appdata.xml
appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
# install licenses
cp -a lib/third_party/nativefiledialog/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/nativefiledialog-LICENSE
cp -a lib/third_party/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
cp -a lib/third_party/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
cp -a lib/third_party/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
cp -a lib/third_party/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
cp -a lib/external/nativefiledialog/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/nativefiledialog-LICENSE
cp -a lib/external/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
cp -a lib/external/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
cp -a lib/external/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
cp -a lib/external/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
%files

4
dist/web/Dockerfile vendored
View File

@@ -37,7 +37,6 @@ mkdir -p $VCPKG_DEFAULT_BINARY_CACHE
/vcpkg/vcpkg install --triplet=wasm32-emscripten libmagic
/vcpkg/vcpkg install --triplet=wasm32-emscripten freetype
/vcpkg/vcpkg install --triplet=wasm32-emscripten mbedtls
/vcpkg/vcpkg install --triplet=wasm32-emscripten libarchive
EOF
# Build ImHex
@@ -55,7 +54,6 @@ ccache -zs
cmake /imhex \
-DIMHEX_OFFLINE_BUILD=ON \
-DIMHEX_STATIC_LINK_PLUGINS=ON \
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
-DNATIVE_CMAKE_C_COMPILER=gcc \
-DNATIVE_CMAKE_CXX_COMPILER=g++ \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -85,8 +83,6 @@ COPY --from=build [ \
"/build/favicon.ico", \
"/build/icon.png", \
"/build/manifest.json", \
"/build/robots.txt", \
"/build/sitemap.xml", \
\
# Destination \
"./" \

View File

@@ -1,22 +1,23 @@
<!doctype html>
<html lang="en-us">
<head>
<title>ImHex Web - Free Online Hex Editor for Reverse Engineers</title>
<link rel="manifest" href="manifest.json">
<link rel="manifest" href="manifest.json" />
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Primary Meta Tags -->
<title>ImHex Web - Online Hex Editor</title>
<meta name="title" content="ImHex">
<meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts.">
<meta name="description" content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="apple-touch-icon" href="icon.png">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://imhex.werwolv.net/">
<meta property="og:title" content="ImHex Web - Online Hex Editor">
<meta property="og:description">
<meta name="description" content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<!-- Twitter -->
@@ -27,7 +28,9 @@
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="application/ld+json">
{
@@ -57,41 +60,15 @@
}
</script>
<title>ImHex Web</title>
<script src="enable-threads.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="loading" class="centered">
<img src="https://raw.githubusercontent.com/WerWolv/ImHex/master/plugins/builtin/romfs/assets/dark/banner.png" id="logo" alt="ImHex Logo">
<h1>A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</h1>
<h2>Available both natively and on the web</h2>
<h5>ImHex runs directly in your web browser with the help of Emscripten and WebAssembly.</h5>
<div style="height: 50%">
<div style="height: 30%"> </div>
<h2 id="not_working">
Not loading in your Browser? <a href="https://imhex.werwolv.net">Try the native version</a>
</h2>
<div style="height: 50%"></div>
</div>
<div class="loading_ripple">
<div class="lds-ripple"><div></div><div></div></div>
</div>
<div style="height: 10%">
</div>
<div class="footer">
<a href="https://imhex.werwolv.net">Homepage</a>
<p>Made with ♥️ by the ImHex Team</p>
<a href="https://github.com/WerWolv/ImHex">GitHub</a>
</div>
</div>
<p id="loading_text">ImHex is loading...</p>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script src="wasm-config.js"></script>
<script async src="imhex.js"></script>
<script type="text/javascript" src="wasm-config.js"></script>
<script async type="text/javascript" src="imhex.js"></script>
</body>
</html>

View File

@@ -1,4 +0,0 @@
User-agent: *
Allow: /
Sitemap: https://imhex.werwolv.net/sitemap.xml

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://web.imhex.werwolv.net/</loc>
<lastmod>2023-12-07T22:53:06+00:00</lastmod>
</url>
</urlset>

View File

@@ -1,6 +1,6 @@
html, body {
height: 100%;
margin: 0;
margin: 0px;
user-select: none;
}
@@ -16,120 +16,21 @@ body {
margin-left: auto;
margin-right: auto;
display: none;
border: 0 none;
border: 0px none;
}
h1, h2, h5 {
color: #F0F0F0;
font-size: 20px;
font-family: monospace;
width: 100%;
text-align: center;
margin-top: 60px;
margin-bottom: 10px;
}
h2 {
margin-top: 15px;
font-size: 17px;
}
h5 {
margin-top: 0;
font-size: 17px;
}
#not_working {
opacity: 0;
}
#not_working.visible {
opacity: 1;
transition: opacity 2s ease;
}
a {
color: #7893ff;
text-decoration: none;
}
a:hover {
text-shadow: #3a4677 0 0 10px;
}
.footer {
width: 100%;
height: 20px;
position: absolute;
bottom: 0;
text-align: center;
color: #F0F0F0;
background-color: #0A0A0A;
padding: 10px;
font-family: monospace;
font-size: 15px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
gap: 10%;
}
.centered {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.canvas_full_screen {
width: 100%;
height: 100%;
}
.lds-ripple {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ripple div {
position: absolute;
border: 4px solid #fff;
opacity: 1;
border-radius: 50%;
animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
top: 0;
left: 0;
}
.lds-ripple div:nth-child(2) {
animation-delay: -0.5s;
}
@keyframes lds-ripple {
0% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 0;
}
4.9% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 0;
}
5% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 1;
}
100% {
top: 0;
left: 0;
width: 72px;
height: 72px;
opacity: 0;
}
#loading_text {
color: #F0F0F0;
font-size: 30px;
font-family: monospace;
width: 100%;
text-align: center;
}

View File

@@ -30,22 +30,16 @@ function glfwCreateStandardCursorCustom(shape) {
return shape
}
var notWorkingTimer = setTimeout(() => {
document.getElementById("not_working").classList.add("visible")
}, 5000);
var Module = {
preRun: [],
postRun: [],
onRuntimeInitialized: function() {
// Triggered when the wasm module is loaded and ready to use.
document.getElementById("loading").style.display = "none"
document.getElementById("loading_text").style.display = "none"
document.getElementById("canvas").style.display = "initial"
clearTimeout(notWorkingTimer);
},
print: (function() { })(),
printErr: function(text) { },
printErr: function(text) { },
canvas: (function() {
let canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
@@ -73,10 +67,4 @@ function js_resizeCanvas() {
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
canvas.classList.add("canvas_full_screen")
if (GLFW.active && GLFW.active.windowPosFunc) {
getWasmTableEntry(GLFW.active.windowPosFunc)(GLFW.active.id, GLFW.active.x, GLFW.active.y);
}
GLFW.onWindowSizeChanged();
}

40
lib/external/imgui/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.16)
project(imgui)
set(CMAKE_CXX_STANDARD 17)
find_package(PkgConfig REQUIRED)
find_package(Freetype REQUIRED)
find_package(OpenGL REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_library(imgui OBJECT
source/imgui.cpp
source/imgui_demo.cpp
source/imgui_draw.cpp
include/misc/freetype/imgui_freetype.cpp # TODO move source and includes in the same directory
source/imgui_impl_glfw.cpp
source/imgui_impl_opengl3.cpp
source/imgui_tables.cpp
source/imgui_widgets.cpp
source/TextEditor.cpp
source/imnodes.cpp
source/implot.cpp
source/implot_items.cpp
source/implot_demo.cpp
source/fonts/fontawesome_font.c
source/fonts/codicons_font.c
source/fonts/unifont_font.c
)
target_compile_definitions(imgui PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLAD)
target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="imgui_config.h")
target_compile_options(imgui PRIVATE -Wno-unknown-warning-option)
target_include_directories(imgui PUBLIC include ${FREETYPE_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS} ${OpenGL_INCLUDE_DIRS})
target_link_directories(imgui PUBLIC ${GLFW_LIBRARY_DIRS} ${OpenGL_LIBRARY_DIRS})
target_link_libraries(imgui PUBLIC Freetype::Freetype ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES})

View File

@@ -9,7 +9,7 @@ extern const unsigned int codicons_compressed_size;
extern const unsigned int codicons_compressed_data[52184/4];
#define ICON_MIN_VS 0xea60
#define ICON_MAX_VS 0xec19
#define ICON_MAX_VS 0xebdd
#define ICON_VS_ADD "\xee\xa9\xa0" // U+ea60
#define ICON_VS_PLUS "\xee\xa9\xa0" // U+ea60
#define ICON_VS_GIST_NEW "\xee\xa9\xa0" // U+ea60
@@ -473,4 +473,3 @@ extern const unsigned int codicons_compressed_data[52184/4];
#define ICON_VS_GIT_PULL_REQUEST_DRAFT "\xee\xaf\x9b" // U+ebdb
#define ICON_VS_DEBUG_ALL "\xee\xaf\x9c" // U+ebdc
#define ICON_VS_DEBUG_COVERAGE "\xee\xaf\x9d" // U+ebdd
#define ICON_VS_CHIP "\xee\xb0\x99" // U+ec19

File diff suppressed because it is too large Load Diff

View File

@@ -126,19 +126,3 @@ namespace ImGui
void MyFunction(const char* name, const MyMatrix44& v);
}
*/
#define IMGUI_ENABLE_TEST_ENGINE
// IMPLOT CONFIG
#define IMPLOT_CUSTOM_NUMERIC_TYPES (ImS8)(ImU8)(ImS16)(ImU16)(ImS32)(ImU32)(ImS64)(ImU64)(float)(double)(long double)
#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER)
#define IM_FLOOR IM_TRUNC
#define IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IMGUI_DISABLE_OBSOLETE_KEYIO
#define IMGUI_ENABLE_FREETYPE
#define ImDrawIdx unsigned int
#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX

View File

@@ -0,0 +1,9 @@
// ImGui config (check imconfig.h for more information about these definitions)
#pragma once
#define IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IMGUI_DISABLE_OBSOLETE_KEYIO
#define IMGUI_ENABLE_FREETYPE
#define ImDrawIdx unsigned int
#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX

View File

@@ -16,15 +16,11 @@
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
struct GLFWwindow;
struct GLFWmonitor;
@@ -54,5 +50,3 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -8,18 +8,10 @@
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// About WebGL/ES:
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
// - This is done automatically on iOS, Android and Emscripten targets.
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// About GLSL version:
// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
@@ -28,7 +20,6 @@
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Backend API
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
@@ -63,5 +54,3 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
#endif
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -32,12 +32,6 @@
#ifndef __gl3w_h_
#define __gl3w_h_
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#elif !defined(__EMSCRIPTEN__)
#include <GL/gl.h>
#endif
#if __has_include(<KHR/khrplatform.h>)
#include <KHR/khrplatform.h>
#else
@@ -1163,9 +1157,7 @@ typedef khronos_uint16_t GLhalf;
#define GL_TEXTURE_DEPTH_TYPE 0x8C16
#define GL_UNSIGNED_NORMALIZED 0x8C17
#define GL_FRAMEBUFFER_BINDING 0x8CA6
#ifndef __APPLE__
#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
#endif
#define GL_RENDERBUFFER_BINDING 0x8CA7
#define GL_READ_FRAMEBUFFER 0x8CA8
#define GL_DRAW_FRAMEBUFFER 0x8CA9

View File

@@ -1,6 +1,6 @@
// MIT License
// Copyright (c) 2023 Evan Pezent
// Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.17
// ImPlot v0.14
// Table of Contents:
//
@@ -60,7 +60,7 @@
#endif
// ImPlot version string.
#define IMPLOT_VERSION "0.17"
#define IMPLOT_VERSION "0.14"
// Indicates variable should deduced automatically.
#define IMPLOT_AUTO -1
// Special color used to indicate that a color should be deduced automatically.
@@ -135,9 +135,10 @@ enum ImPlotFlags_ {
ImPlotFlags_NoInputs = 1 << 3, // the user will not be able to interact with the plot
ImPlotFlags_NoMenus = 1 << 4, // the user will not be able to open context menus
ImPlotFlags_NoBoxSelect = 1 << 5, // the user will not be able to box-select
ImPlotFlags_NoFrame = 1 << 6, // the ImGui frame will not be rendered
ImPlotFlags_Equal = 1 << 7, // x and y axes pairs will be constrained to have the same units/pixel
ImPlotFlags_Crosshairs = 1 << 8, // the default mouse cursor will be replaced with a crosshair when hovered
ImPlotFlags_NoChild = 1 << 6, // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications)
ImPlotFlags_NoFrame = 1 << 7, // the ImGui frame will not be rendered
ImPlotFlags_Equal = 1 << 8, // x and y axes pairs will be constrained to have the same units/pixel
ImPlotFlags_Crosshairs = 1 << 9, // the default mouse cursor will be replaced with a crosshair when hovered
ImPlotFlags_CanvasOnly = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText
};
@@ -286,9 +287,8 @@ enum ImPlotInfLinesFlags_ {
// Flags for PlotPieChart
enum ImPlotPieChartFlags_ {
ImPlotPieChartFlags_None = 0, // default
ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
ImPlotPieChartFlags_IgnoreHidden = 1 << 11 // ignore hidden slices when drawing the pie chart (as if they were not there)
ImPlotPieChartFlags_None = 0, // default
ImPlotPieChartFlags_Normalize = 1 << 10 // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
};
// Flags for PlotHeatmap
@@ -464,43 +464,41 @@ enum ImPlotBin_ {
};
// Double precision version of ImVec2 used by ImPlot. Extensible by end users.
IM_MSVC_RUNTIME_CHECKS_OFF
struct ImPlotPoint {
double x, y;
constexpr ImPlotPoint() : x(0.0), y(0.0) { }
constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y) { }
constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y) { }
double& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((double*)(void*)(char*)this)[idx]; }
double operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const double*)(const void*)(const char*)this)[idx]; }
ImPlotPoint() { x = y = 0.0; }
ImPlotPoint(double _x, double _y) { x = _x; y = _y; }
ImPlotPoint(const ImVec2& p) { x = p.x; y = p.y; }
double operator[] (size_t idx) const { return (&x)[idx]; }
double& operator[] (size_t idx) { return (&x)[idx]; }
#ifdef IMPLOT_POINT_CLASS_EXTRA
IMPLOT_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h
// to convert back and forth between your math types and ImPlotPoint.
#endif
};
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Range defined by a min/max value.
struct ImPlotRange {
double Min, Max;
constexpr ImPlotRange() : Min(0.0), Max(0.0) { }
constexpr ImPlotRange(double _min, double _max) : Min(_min), Max(_max) { }
bool Contains(double value) const { return value >= Min && value <= Max; }
double Size() const { return Max - Min; }
double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; }
ImPlotRange() { Min = 0; Max = 0; }
ImPlotRange(double _min, double _max) { Min = _min; Max = _max; }
bool Contains(double value) const { return value >= Min && value <= Max; }
double Size() const { return Max - Min; }
double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; }
};
// Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max().
struct ImPlotRect {
ImPlotRange X, Y;
constexpr ImPlotRect() : X(0.0,0.0), Y(0.0,0.0) { }
constexpr ImPlotRect(double x_min, double x_max, double y_min, double y_max) : X(x_min, x_max), Y(y_min, y_max) { }
bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); }
bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); }
ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); }
ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); }
ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); }
ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); }
ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); }
ImPlotRect() { }
ImPlotRect(double x_min, double x_max, double y_min, double y_max) { X.Min = x_min; X.Max = x_max; Y.Min = y_min; Y.Max = y_max; }
bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); }
bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); }
ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); }
ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); }
ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); }
ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); }
ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); }
};
// Plot style structure
@@ -730,7 +728,7 @@ IMPLOT_API void EndSubplots();
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label.
IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0);
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. Inversion with v_min > v_max is not supported; use SetupAxisLimits instead.
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot.
IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);
@@ -756,7 +754,7 @@ IMPLOT_API void SetupAxes(const char* x_label, const char* y_label, ImPlotAxisFl
// Sets the primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits).
IMPLOT_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once);
// Sets up the plot legend. This can also be called immediately after BeginSubplots when using ImPlotSubplotFlags_ShareItems.
// Sets up the plot legend.
IMPLOT_API void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags=0);
// Set the location of the current plot's mouse position text (default = South|East).
IMPLOT_API void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags=0);
@@ -893,7 +891,6 @@ IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int co
IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data=nullptr, double angle0=90, ImPlotPieChartFlags flags=0);
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0);
// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels.
@@ -926,18 +923,16 @@ IMPLOT_API void PlotDummy(const char* label_id, ImPlotDummyFlags flags=0);
// The following can be used to render interactive elements and/or annotations.
// Like the item plotting functions above, they apply to the current x and y
// axes, which can be changed with `SetAxis/SetAxes`. These functions return true
// when user interaction causes the provided coordinates to change. Additional
// user interactions can be retrieved through the optional output parameters.
// axes, which can be changed with `SetAxis/SetAxes`.
// Shows a draggable point at x,y. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr);
IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags=0);
// Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr);
IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags=0);
// Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr);
IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags=0);
// Shows a draggable and resizeable rectangle.
IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr);
IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags=0);
// Shows an annotation callout at a chosen point. Clamping keeps annotations in the plot area. Annotations are always rendered on top.
IMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, bool round = false);

View File

@@ -1,6 +1,6 @@
// MIT License
// Copyright (c) 2023 Evan Pezent
// Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.17
// ImPlot v0.14
// You may use this file to debug, understand or extend ImPlot features but we
// don't provide any guarantee of forward compatibility!
@@ -907,9 +907,8 @@ struct ImPlotAxis
}
void PullLinks() {
if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); }
else if (LinkedMin) { SetMin(*LinkedMin,true); }
else if (LinkedMax) { SetMax(*LinkedMax,true); }
if (LinkedMin) { SetMin(*LinkedMin,true); }
if (LinkedMax) { SetMax(*LinkedMax,true); }
}
};
@@ -966,11 +965,9 @@ struct ImPlotLegend
ImPlotLegendFlags PreviousFlags;
ImPlotLocation Location;
ImPlotLocation PreviousLocation;
ImVec2 Scroll;
ImVector<int> Indices;
ImGuiTextBuffer Labels;
ImRect Rect;
ImRect RectClamped;
bool Hovered;
bool Held;
bool CanGoInside;
@@ -980,7 +977,6 @@ struct ImPlotLegend
CanGoInside = true;
Hovered = Held = false;
Location = PreviousLocation = ImPlotLocation_NorthWest;
Scroll = ImVec2(0,0);
}
void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
@@ -1140,6 +1136,7 @@ struct ImPlotSubplot {
ID = 0;
Flags = PreviousFlags = ImPlotSubplotFlags_None;
Rows = Cols = CurrentIdx = 0;
FrameHovered = false;
Items.Legend.Location = ImPlotLocation_North;
Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
Items.Legend.CanGoInside = false;
@@ -1218,6 +1215,9 @@ struct ImPlotContext {
ImPlotAnnotationCollection Annotations;
ImPlotTagCollection Tags;
// Flags
bool ChildWindowMade;
// Style and Colormaps
ImPlotStyle Style;
ImVector<ImGuiColorMod> ColorModifiers;
@@ -1414,15 +1414,13 @@ IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bo
// Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
// Calculates the bounding box size of a legend _before_ clipping.
// Calculates the bounding box size of a legend
IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);
// Clips calculated legend size
IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad);
// Renders legend entries into a bounding box
IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);
// Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window! This is not thoroughly tested nor scrollable!).
// Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window!).
IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true);
// Shows a legend's context menu.
// Shows an legends's context menu.
IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible);
//-----------------------------------------------------------------------------

View File

@@ -6,14 +6,13 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
// 2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG' (#6591)
// 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
// 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
// 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
@@ -34,8 +33,6 @@
// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_freetype.h"
#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*,
#include <stdint.h>
@@ -45,15 +42,6 @@
#include FT_GLYPH_H // <freetype/ftglyph.h>
#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
#include FT_OTSVG_H // <freetype/otsvg.h>
#include FT_BBOX_H // <freetype/ftbbox.h>
#include <lunasvg.h>
#if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
#error IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
#endif
#endif
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
@@ -64,10 +52,8 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsubobject-linkage" // warning: 'xxxx' has a field 'xxxx' whose type uses the anonymous namespace
#endif
#endif
//-------------------------------------------------------------------------
// Data
@@ -82,14 +68,6 @@ static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFre
static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
static void* GImGuiFreeTypeAllocatorUserData = nullptr;
// Lunasvg support
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state);
static void ImGuiLunasvgPortFree(FT_Pointer* state);
static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state);
static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state);
#endif
//-------------------------------------------------------------------------
// Code
//-------------------------------------------------------------------------
@@ -167,8 +145,6 @@ namespace
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
FT_Int32 LoadFlags;
FT_Render_Mode RenderMode;
float RasterizationDensity;
float InvRasterizationDensity;
};
// From SDL_ttf: Handy routines for converting from fixed point
@@ -211,9 +187,6 @@ namespace
if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
LoadFlags |= FT_LOAD_COLOR;
RasterizationDensity = cfg.RasterizerDensity;
InvRasterizationDensity = 1.0f / RasterizationDensity;
memset(&Info, 0, sizeof(Info));
SetPixelHeight((uint32_t)cfg.SizePixels);
@@ -237,19 +210,19 @@ namespace
FT_Size_RequestRec req;
req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0;
req.height = (uint32_t)(pixel_height * 64 * RasterizationDensity);
req.height = (uint32_t)pixel_height * 64;
req.horiResolution = 0;
req.vertResolution = 0;
FT_Request_Size(Face, &req);
// Update font info
FT_Size_Metrics metrics = Face->size->metrics;
Info.PixelHeight = (uint32_t)(pixel_height * InvRasterizationDensity);
Info.Ascender = (float)FT_CEIL(metrics.ascender) * InvRasterizationDensity;
Info.Descender = (float)FT_CEIL(metrics.descender) * InvRasterizationDensity;
Info.LineSpacing = (float)FT_CEIL(metrics.height) * InvRasterizationDensity;
Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * InvRasterizationDensity;
Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * InvRasterizationDensity;
Info.PixelHeight = (uint32_t)pixel_height;
Info.Ascender = (float)FT_CEIL(metrics.ascender);
Info.Descender = (float)FT_CEIL(metrics.descender);
Info.LineSpacing = (float)FT_CEIL(metrics.height);
Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender);
Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance);
}
const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint)
@@ -269,14 +242,7 @@ namespace
// Need an outline for this to work
FT_GlyphSlot slot = Face->glyph;
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG);
#else
#if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
#endif
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
// Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
@@ -703,15 +669,15 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
const int ty = pack_rect.y + padding;
// Register glyph
float x0 = info.OffsetX * src_tmp.Font.InvRasterizationDensity + font_off_x;
float y0 = info.OffsetY * src_tmp.Font.InvRasterizationDensity + font_off_y;
float x1 = x0 + info.Width * src_tmp.Font.InvRasterizationDensity;
float y1 = y0 + info.Height * src_tmp.Font.InvRasterizationDensity;
float x0 = info.OffsetX + font_off_x;
float y0 = info.OffsetY + font_off_y;
float x1 = x0 + info.Width;
float y1 = y0 + info.Height;
float u0 = (tx) / (float)atlas->TexWidth;
float v0 = (ty) / (float)atlas->TexHeight;
float u1 = (tx + info.Width) / (float)atlas->TexWidth;
float v1 = (ty + info.Height) / (float)atlas->TexHeight;
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity);
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
@@ -804,14 +770,6 @@ static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
// If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
FT_Add_Default_Modules(ft_library);
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// Install svg hooks for FreeType
// https://freetype.org/freetype2/docs/reference/ft2-properties.html#svg-hooks
// https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html#svg_fonts
SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot };
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", &hooks);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
FT_Done_Library(ft_library);
@@ -832,115 +790,6 @@ void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* u
GImGuiFreeTypeAllocatorUserData = user_data;
}
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c
// The original code from the demo is licensed under CeCILL-C Free Software License Agreement (https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT)
struct LunasvgPortState
{
FT_Error err = FT_Err_Ok;
lunasvg::Matrix matrix;
std::unique_ptr<lunasvg::Document> svg = nullptr;
};
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* _state)
{
*_state = IM_NEW(LunasvgPortState)();
return FT_Err_Ok;
}
static void ImGuiLunasvgPortFree(FT_Pointer* _state)
{
IM_DELETE(*(LunasvgPortState**)_state);
}
static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state)
{
LunasvgPortState* state = *(LunasvgPortState**)_state;
// If there was an error while loading the svg in ImGuiLunasvgPortPresetSlot(), the renderer hook still get called, so just returns the error.
if (state->err != FT_Err_Ok)
return state->err;
// rows is height, pitch (or stride) equals to width * sizeof(int32)
lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
state->svg->setMatrix(state->svg->matrix().identity()); // Reset the svg matrix to the default value
state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated
state->err = FT_Err_Ok;
return state->err;
}
static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state)
{
FT_SVG_Document document = (FT_SVG_Document)slot->other;
LunasvgPortState* state = *(LunasvgPortState**)_state;
FT_Size_Metrics& metrics = document->metrics;
// This function is called twice, once in the FT_Load_Glyph() and another right before ImGuiLunasvgPortRender().
// If it's the latter, don't do anything because it's // already done in the former.
if (cache)
return state->err;
state->svg = lunasvg::Document::loadFromData((const char*)document->svg_document, document->svg_document_length);
if (state->svg == nullptr)
{
state->err = FT_Err_Invalid_SVG_Document;
return state->err;
}
lunasvg::Box box = state->svg->box();
double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h);
double xx = (double)document->transform.xx / (1 << 16);
double xy = -(double)document->transform.xy / (1 << 16);
double yx = -(double)document->transform.yx / (1 << 16);
double yy = (double)document->transform.yy / (1 << 16);
double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem;
double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem;
// Scale and transform, we don't translate the svg yet
state->matrix.identity();
state->matrix.scale(scale, scale);
state->matrix.transform(xx, xy, yx, yy, x0, y0);
state->svg->setMatrix(state->matrix);
// Pre-translate the matrix for the rendering step
state->matrix.translate(-box.x, -box.y);
// Get the box again after the transformation
box = state->svg->box();
// Calculate the bitmap size
slot->bitmap_left = FT_Int(box.x);
slot->bitmap_top = FT_Int(-box.y);
slot->bitmap.rows = (unsigned int)(ImCeil((float)box.h));
slot->bitmap.width = (unsigned int)(ImCeil((float)box.w));
slot->bitmap.pitch = slot->bitmap.width * 4;
slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
// Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
double metrics_width = box.w;
double metrics_height = box.h;
double horiBearingX = box.x;
double horiBearingY = -box.y;
double vertBearingX = slot->metrics.horiBearingX / 64.0 - slot->metrics.horiAdvance / 64.0 / 2.0;
double vertBearingY = (slot->metrics.vertAdvance / 64.0 - slot->metrics.height / 64.0) / 2.0;
slot->metrics.width = FT_Pos(IM_ROUND(metrics_width * 64.0)); // Using IM_ROUND() assume width and height are positive
slot->metrics.height = FT_Pos(IM_ROUND(metrics_height * 64.0));
slot->metrics.horiBearingX = FT_Pos(horiBearingX * 64);
slot->metrics.horiBearingY = FT_Pos(horiBearingY * 64);
slot->metrics.vertBearingX = FT_Pos(vertBearingX * 64);
slot->metrics.vertBearingY = FT_Pos(vertBearingY * 64);
if (slot->metrics.vertAdvance == 0)
slot->metrics.vertAdvance = FT_Pos(metrics_height * 1.2 * 64.0);
state->err = FT_Err_Ok;
return state->err;
}
#endif // #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
//-----------------------------------------------------------------------------
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
@@ -948,5 +797,3 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -2,8 +2,8 @@
// (headers)
#pragma once
#include "imgui.h" // IMGUI_API
#ifndef IMGUI_DISABLE
// Forward declarations
struct ImFontAtlas;
@@ -48,5 +48,3 @@ namespace ImGuiFreeType
static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
#endif
}
#endif // #ifndef IMGUI_DISABLE

View File

@@ -642,7 +642,7 @@ void TextEditor::HandleKeyboardInputs() {
SetSelection(wordStart, wordEnd);
Backspace();
}
else if (!IsReadOnly() && !ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
Backspace();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace))) {
auto wordEnd = GetCursorPosition();
@@ -1184,26 +1184,10 @@ void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) {
} else if (aChar == '\t') {
auto &line = mLines[coord.mLine];
auto cindex = GetCharacterIndex(coord);
if (!aShift) {
auto spacesToInsert = mTabSize - (cindex % mTabSize);
for (int j = 0; j < spacesToInsert; j++)
line.insert(line.begin() + cindex, Glyph(' ', PaletteIndex::Background));
SetCursorPosition(Coordinates(coord.mLine, GetCharacterColumn(coord.mLine, cindex + spacesToInsert)));
} else {
auto spacesToRemove = (cindex % mTabSize);
if (spacesToRemove == 0) spacesToRemove = 4;
for (int j = 0; j < spacesToRemove; j++) {
if ((line.begin() + cindex - 1)->mChar == ' ') {
line.erase(line.begin() + cindex - 1);
cindex -= 1;
}
}
SetCursorPosition(Coordinates(coord.mLine, GetCharacterColumn(coord.mLine, std::max(0, cindex))));
}
auto spacesToInsert = mTabSize - (cindex % mTabSize);
for (int j = 0; j < spacesToInsert; j++)
line.insert(line.begin() + cindex, Glyph(' ', PaletteIndex::Background));
SetCursorPosition(Coordinates(coord.mLine, GetCharacterColumn(coord.mLine, cindex + spacesToInsert)));
} else {
char buf[7];
int e = ImTextCharToUtf8(buf, 7, aChar);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,18 +16,12 @@
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
// 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
// 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702)
// 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034)
// 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240)
@@ -38,7 +32,7 @@
// 2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
// 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position *EDIT* Reverted 2023-07-18.
// 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position.
// 2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX.
// 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11.
// 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend.
@@ -75,7 +69,6 @@
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_glfw.h"
// Clang warnings with -Weverything
@@ -114,11 +107,7 @@
#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_HOVERED
#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwSetWindowOpacity
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale
#if defined(__EMSCRIPTEN__) || defined(__SWITCH__) // no Vulkan support in GLFW for Emscripten or homebrew Nintendo Switch
#define GLFW_HAS_VULKAN (0)
#else
#define GLFW_HAS_VULKAN (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwCreateWindowSurface
#endif
#define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwFocusWindow
#define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW
#define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorWorkarea
@@ -170,7 +159,7 @@ struct ImGui_ImplGlfw_Data
GLFWcharfun PrevUserCallbackChar;
GLFWmonitorfun PrevUserCallbackMonitor;
#ifdef _WIN32
WNDPROC PrevWndProc;
WNDPROC GlfwWndProc;
#endif
ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -313,18 +302,6 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
case GLFW_KEY_F10: return ImGuiKey_F10;
case GLFW_KEY_F11: return ImGuiKey_F11;
case GLFW_KEY_F12: return ImGuiKey_F12;
case GLFW_KEY_F13: return ImGuiKey_F13;
case GLFW_KEY_F14: return ImGuiKey_F14;
case GLFW_KEY_F15: return ImGuiKey_F15;
case GLFW_KEY_F16: return ImGuiKey_F16;
case GLFW_KEY_F17: return ImGuiKey_F17;
case GLFW_KEY_F18: return ImGuiKey_F18;
case GLFW_KEY_F19: return ImGuiKey_F19;
case GLFW_KEY_F20: return ImGuiKey_F20;
case GLFW_KEY_F21: return ImGuiKey_F21;
case GLFW_KEY_F22: return ImGuiKey_F22;
case GLFW_KEY_F23: return ImGuiKey_F23;
case GLFW_KEY_F24: return ImGuiKey_F24;
default: return ImGuiKey_None;
}
}
@@ -444,6 +421,8 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
bd->PrevUserCallbackCursorPos(window, x, y);
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
return;
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@@ -464,6 +443,8 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
bd->PrevUserCallbackCursorEnter(window, entered);
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
return;
ImGuiIO& io = ImGui::GetIO();
if (entered)
@@ -514,7 +495,48 @@ static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEven
#endif
#ifdef _WIN32
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen.
// Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently.
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
return ImGuiMouseSource_Pen;
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
return ImGuiMouseSource_TouchScreen;
return ImGuiMouseSource_Mouse;
}
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
switch (msg)
{
case WM_MOUSEMOVE: case WM_NCMOUSEMOVE:
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
break;
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED
case WM_NCHITTEST:
{
// Let mouse pass-through the window. This will allow the backend to call io.AddMouseViewportEvent() properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
if (viewport && (viewport->Flags & ImGuiViewportFlags_NoInputs))
return HTTRANSPARENT;
break;
}
#endif
}
return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam);
}
#endif
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
@@ -654,8 +676,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32
bd->PrevWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
IM_ASSERT(bd->PrevWndProc != nullptr);
bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
IM_ASSERT(bd->GlfwWndProc != nullptr);
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
@@ -688,18 +710,15 @@ void ImGui_ImplGlfw_Shutdown()
if (bd->InstalledCallbacks)
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
#ifdef __EMSCRIPTEN__
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr);
#endif
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
// Windows: restore our WndProc hook
// Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc);
bd->PrevWndProc = nullptr;
::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc);
bd->GlfwWndProc = nullptr;
#endif
io.BackendPlatformName = nullptr;
@@ -714,6 +733,11 @@ static void ImGui_ImplGlfw_UpdateMouseData()
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
if (glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
{
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
return;
}
ImGuiID mouse_viewport_id = 0;
const ImVec2 mouse_pos_prev = io.MousePos;
@@ -869,14 +893,17 @@ static void ImGui_ImplGlfw_UpdateMonitors()
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
bd->WantUpdateMonitors = false;
int monitors_count = 0;
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
if (monitors_count == 0) // Preserve existing monitor list if there are none. Happens on macOS sleeping (#5683)
return;
platform_io.Monitors.resize(0);
// IMHEX PATCH BEGIN
// REASON: Prevent occasional crash when having ImHex open and connecting to the computer over RDP
// NOTE: Untested with this ImGui version
if (monitors_count > 0)
platform_io.Monitors.resize(0);
// IMHEX PATCH END
bd->WantUpdateMonitors = false;
for (int n = 0; n < monitors_count; n++)
{
ImGuiPlatformMonitor monitor;
@@ -900,12 +927,7 @@ static void ImGui_ImplGlfw_UpdateMonitors()
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
float x_scale, y_scale;
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
// IMHEX PATCH BEGIN
// REASON: Prevent occasional crash when a monitor connection status is changed
if (x_scale > 0)
monitor.DpiScale = x_scale;
// IMHEX PATCH END
monitor.DpiScale = x_scale;
#endif
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
platform_io.Monitors.push_back(monitor);
@@ -930,10 +952,7 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateMonitors();
// Setup time step
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
double current_time = glfwGetTime();
if (current_time <= bd->Time)
current_time = bd->Time + 0.00001f;
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time;
@@ -957,11 +976,8 @@ struct ImGui_ImplGlfw_ViewportData
bool WindowOwned;
int IgnoreWindowPosEventFrame;
int IgnoreWindowSizeEventFrame;
#ifdef _WIN32
WNDPROC PrevWndProc;
#endif
ImGui_ImplGlfw_ViewportData() { memset(this, 0, sizeof(*this)); IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = -1; }
ImGui_ImplGlfw_ViewportData() { Window = nullptr; WindowOwned = false; IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = -1; }
~ImGui_ImplGlfw_ViewportData() { IM_ASSERT(Window == nullptr); }
};
@@ -1099,8 +1115,9 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
// GLFW hack: install hook for WM_NCHITTEST message handler
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC);
IM_ASSERT(bd->GlfwWndProc == (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC));
::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
@@ -1286,63 +1303,6 @@ static void ImGui_ImplGlfw_ShutdownPlatformInterface()
ImGui::DestroyPlatformWindows();
}
//-----------------------------------------------------------------------------
// WndProc hook (declared here because we will need access to ImGui_ImplGlfw_ViewportData)
#ifdef _WIN32
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
return ImGuiMouseSource_Pen;
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
return ImGuiMouseSource_TouchScreen;
return ImGuiMouseSource_Mouse;
}
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
WNDPROC prev_wndproc = bd->PrevWndProc;
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
if (viewport != NULL)
if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData)
prev_wndproc = vd->PrevWndProc;
switch (msg)
{
// GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen.
// Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently.
case WM_MOUSEMOVE: case WM_NCMOUSEMOVE:
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
break;
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED
case WM_NCHITTEST:
{
// Let mouse pass-through the window. This will allow the backend to call io.AddMouseViewportEvent() properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
if (viewport && (viewport->Flags & ImGuiViewportFlags_NoInputs))
return HTTRANSPARENT;
break;
}
#endif
}
return ::CallWindowProc(prev_wndproc, hWnd, msg, wParam, lParam);
}
#endif // #ifdef _WIN32
//-----------------------------------------------------------------------------
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -8,25 +8,14 @@
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// About WebGL/ES:
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
// - This is done automatically on iOS, Android and Emscripten targets.
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accomodating for NetBSD systems having only "libGL.so.3" available. (#6983)
// 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445)
// 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333)
// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
// 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333)
// 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224)
@@ -111,10 +100,13 @@
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t
#else
#include <stdint.h> // intptr_t
#endif
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
@@ -292,12 +284,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
io.BackendRendererName = "imgui_impl_opengl3";
// Query for GL version (e.g. 320 for GL 3.2)
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GLES 2
bd->GlVersion = 200;
bd->GlProfileIsES2 = true;
#else
// Desktop or GLES 3
#if !defined(IMGUI_IMPL_OPENGL_ES2)
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
@@ -310,15 +297,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
}
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
#if defined(GL_CONTEXT_PROFILE_MASK)
if (bd->GlVersion >= 320)
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
#endif
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
#endif
bd->UseBufferSubData = false;
/*
// Query vendor to enable glBufferSubData kludge
@@ -328,10 +310,16 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->UseBufferSubData = true;
#endif
*/
#elif defined(IMGUI_IMPL_OPENGL_ES2)
bd->GlVersion = 200; // GLES 2
bd->GlProfileIsES2 = true;
#elif defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlVersion = 200; // Don't raise version as it is intended as a desktop version check for now.
bd->GlProfileIsES3 = true;
#endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
@@ -473,9 +461,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, uv)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
}
// OpenGL3 Render function.
@@ -974,13 +962,9 @@ static void ImGui_ImplOpenGL3_ShutdownPlatformInterface()
ImGui::DestroyPlatformWindows();
}
//-----------------------------------------------------------------------------
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -1,6 +1,6 @@
// MIT License
// Copyright (c) 2023 Evan Pezent
// Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.17
// ImPlot v0.14
/*
@@ -31,9 +31,6 @@ Below is a change-log of API breaking changes only. If you are using one of the
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
You can read releases logs https://github.com/epezent/implot/releases for more details.
- 2023/08/20 (0.17) - ImPlotFlags_NoChild was removed as child windows are no longer needed to capture scroll. You can safely remove this flag if you were using it.
- 2023/06/26 (0.15) - Various build fixes related to updates in Dear ImGui internals.
- 2022/11/25 (0.15) - Make PlotText honor ImPlotItemFlags_NoFit.
- 2022/06/19 (0.14) - The signature of ColormapScale has changed to accommodate a new ImPlotColormapScaleFlags parameter
- 2022/06/17 (0.14) - **IMPORTANT** All PlotX functions now take an ImPlotX_Flags `flags` parameter. Where applicable, it is located before the existing `offset` and `stride` parameters.
If you were providing offset and stride values, you will need to update your function call to include a `flags` value. If you fail to do this, you will likely see
@@ -136,11 +133,6 @@ You can read releases logs https://github.com/epezent/implot/releases for more d
#define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All
#endif
// Support for pre-1.89.7 versions.
#if (IMGUI_VERSION_NUM < 18966)
#define ImGuiButtonFlags_AllowOverlap ImGuiButtonFlags_AllowItemOverlap
#endif
// Visual Studio warnings
#ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
@@ -293,35 +285,35 @@ struct ImPlotStyleVarInfo {
static const ImPlotStyleVarInfo GPlotStyleVarInfo[] =
{
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight
{ ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, FillAlpha) }, // ImPlotStyleVar_FillAlpha
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight
{ ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, FillAlpha) }, // ImPlotStyleVar_FillAlpha
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, PlotBorderSize) }, // ImPlotStyleVar_PlotBorderSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MinorAlpha) }, // ImPlotStyleVar_MinorAlpha
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorTickLen) }, // ImPlotStyleVar_MajorTickLen
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorTickLen) }, // ImPlotStyleVar_MinorTickLen
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorTickSize) }, // ImPlotStyleVar_MajorTickSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorTickSize) }, // ImPlotStyleVar_MinorTickSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotBorderSize) }, // ImPlotStyleVar_PlotBorderSize
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorAlpha) }, // ImPlotStyleVar_MinorAlpha
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickLen) }, // ImPlotStyleVar_MajorTickLen
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickLen) }, // ImPlotStyleVar_MinorTickLen
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickSize) }, // ImPlotStyleVar_MajorTickSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickSize) }, // ImPlotStyleVar_MinorTickSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MousePosPadding) }, // ImPlotStyleVar_MousePosPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, AnnotationPadding) }, // ImPlotStyleVar_AnnotationPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, FitPadding) }, // ImPlotStyleVar_FitPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotDefaultSize) }, // ImPlotStyleVar_PlotDefaultSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotMinSize) } // ImPlotStyleVar_PlotMinSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MousePosPadding) }, // ImPlotStyleVar_MousePosPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, AnnotationPadding) }, // ImPlotStyleVar_AnnotationPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, FitPadding) }, // ImPlotStyleVar_FitPadding
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotDefaultSize) }, // ImPlotStyleVar_PlotDefaultSize
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotMinSize) } // ImPlotStyleVar_PlotMinSize
};
static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) {
@@ -341,8 +333,8 @@ void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char *te
ImGuiContext& g = *GImGui;
ImFont* font = g.Font;
// Align to be pixel perfect
pos.x = ImFloor(pos.x);
pos.y = ImFloor(pos.y);
pos.x = IM_FLOOR(pos.x);
pos.y = IM_FLOOR(pos.y);
const float scale = g.FontSize / font->FontSize;
const char* s = text_begin;
int chars_exp = (int)(text_end - s);
@@ -493,6 +485,10 @@ void Initialize(ImPlotContext* ctx) {
}
void ResetCtxForNextPlot(ImPlotContext* ctx) {
// end child window if it was made
if (ctx->ChildWindowMade)
ImGui::EndChild();
ctx->ChildWindowMade = false;
// reset the next plot/item data
ctx->NextPlotData.Reset();
ctx->NextItemData.Reset();
@@ -586,28 +582,6 @@ ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& s
return legend_size;
}
bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad) {
bool clamped = false;
ImRect outer_rect_pad(outer_rect.Min + pad, outer_rect.Max - pad);
if (legend_rect.Min.x < outer_rect_pad.Min.x) {
legend_rect.Min.x = outer_rect_pad.Min.x;
clamped = true;
}
if (legend_rect.Min.y < outer_rect_pad.Min.y) {
legend_rect.Min.y = outer_rect_pad.Min.y;
clamped = true;
}
if (legend_rect.Max.x > outer_rect_pad.Max.x) {
legend_rect.Max.x = outer_rect_pad.Max.x;
clamped = true;
}
if (legend_rect.Max.y > outer_rect_pad.Max.y) {
legend_rect.Max.y = outer_rect_pad.Max.y;
clamped = true;
}
return clamped;
}
int LegendSortingComp(const void* _a, const void* _b) {
ImPlotItemGroup* items = GImPlot->SortItems;
const int a = *(const int*)_a;
@@ -1322,12 +1296,12 @@ bool DragFloat(const char*, F*, float, F, F) {
template <>
bool DragFloat<double>(const char* label, double* v, float v_speed, double v_min, double v_max) {
return ImGui::DragScalar(label, ImGuiDataType_Double, v, v_speed, &v_min, &v_max, "%.3g", 1);
return ImGui::DragScalar(label, ImGuiDataType_Double, v, v_speed, &v_min, &v_max, "%.3f", 1);
}
template <>
bool DragFloat<float>(const char* label, float* v, float v_speed, float v_min, float v_max) {
return ImGui::DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, "%.3g", 1);
return ImGui::DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, "%.3f", 1);
}
inline void BeginDisabledControls(bool cond) {
@@ -1574,7 +1548,7 @@ void ShowPlotContextMenu(ImPlotPlot& plot) {
ImFlipFlag(plot.Flags, ImPlotFlags_Crosshairs);
ImGui::EndMenu();
}
if (gp.CurrentSubplot != nullptr && !ImHasFlag(gp.CurrentSubplot->Flags, ImPlotSubplotFlags_NoMenus)) {
if (gp.CurrentSubplot != nullptr && !ImHasFlag(gp.CurrentPlot->Flags, ImPlotSubplotFlags_NoMenus)) {
ImGui::Separator();
if ((ImGui::BeginMenu("Subplots"))) {
ShowSubplotsContextMenu(*gp.CurrentSubplot);
@@ -1834,7 +1808,7 @@ bool UpdateInput(ImPlotPlot& plot) {
// BUTTON STATE -----------------------------------------------------------
const ImGuiButtonFlags plot_button_flags = ImGuiButtonFlags_AllowOverlap
const ImGuiButtonFlags plot_button_flags = ImGuiButtonFlags_AllowItemOverlap
| ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick
| ImGuiButtonFlags_MouseButtonLeft
@@ -1844,9 +1818,7 @@ bool UpdateInput(ImPlotPlot& plot) {
| plot_button_flags;
const bool plot_clicked = ImGui::ButtonBehavior(plot.PlotRect,plot.ID,&plot.Hovered,&plot.Held,plot_button_flags);
#if (IMGUI_VERSION_NUM < 18966)
ImGui::SetItemAllowOverlap(); // Handled by ButtonBehavior()
#endif
ImGui::SetItemAllowOverlap();
if (plot_clicked) {
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) && IO.MouseClicked[gp.InputMap.Select] && ImHasFlag(IO.KeyMods, gp.InputMap.SelectMod)) {
@@ -1979,12 +1951,10 @@ bool UpdateInput(ImPlotPlot& plot) {
// SCROLL INPUT -----------------------------------------------------------
if (any_hov && ImHasFlag(IO.KeyMods, gp.InputMap.ZoomMod)) {
if (any_hov && IO.MouseWheel != 0 && ImHasFlag(IO.KeyMods, gp.InputMap.ZoomMod)) {
float zoom_rate = gp.InputMap.ZoomRate;
if (IO.MouseWheel == 0.0f)
zoom_rate = 0;
else if (IO.MouseWheel > 0)
if (IO.MouseWheel > 0)
zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate));
ImVec2 rect_size = plot.PlotRect.GetSize();
float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f);
@@ -1995,17 +1965,14 @@ bool UpdateInput(ImPlotPlot& plot) {
const bool equal_zoom = axis_equal && x_axis.OrthoAxis != nullptr;
const bool equal_locked = (equal_zoom != false) && x_axis.OrthoAxis->IsInputLocked();
if (x_hov[i] && !x_axis.IsInputLocked() && !equal_locked) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID);
if (zoom_rate != 0.0f) {
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction);
const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction);
x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l);
x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r);
if (axis_equal && x_axis.OrthoAxis != nullptr)
x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());
changed = true;
}
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction);
const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction);
x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l);
x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r);
if (axis_equal && x_axis.OrthoAxis != nullptr)
x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());
changed = true;
}
}
for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {
@@ -2013,17 +1980,14 @@ bool UpdateInput(ImPlotPlot& plot) {
const bool equal_zoom = axis_equal && y_axis.OrthoAxis != nullptr;
const bool equal_locked = equal_zoom && y_axis.OrthoAxis->IsInputLocked();
if (y_hov[i] && !y_axis.IsInputLocked() && !equal_locked) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID);
if (zoom_rate != 0.0f) {
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction);
const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction);
y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b);
y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t);
if (axis_equal && y_axis.OrthoAxis != nullptr)
y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());
changed = true;
}
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction);
const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction);
y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b);
y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t);
if (axis_equal && y_axis.OrthoAxis != nullptr)
y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());
changed = true;
}
}
}
@@ -2305,19 +2269,19 @@ void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImP
void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags) {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR((gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked) || (gp.CurrentSubplot != nullptr && gp.CurrentPlot == nullptr),
"Setup needs to be called after BeginPlot or BeginSubplots and before any setup locking functions (e.g. PlotX)!");
if (gp.CurrentItems) {
ImPlotLegend& legend = gp.CurrentItems->Legend;
// check and set location
if (location != legend.PreviousLocation)
legend.Location = location;
legend.PreviousLocation = location;
// check and set flags
if (flags != legend.PreviousFlags)
legend.Flags = flags;
legend.PreviousFlags = flags;
}
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,
"Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!");
IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr,
"SetupLegend() needs to be called within an itemized context!");
ImPlotLegend& legend = gp.CurrentItems->Legend;
// check and set location
if (location != legend.PreviousLocation)
legend.Location = location;
legend.PreviousLocation = location;
// check and set flags
if (flags != legend.PreviousFlags)
legend.Flags = flags;
legend.PreviousFlags = flags;
}
void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags) {
@@ -2429,6 +2393,22 @@ bool BeginPlot(const char* title_id, const ImVec2& size, ImPlotFlags flags) {
for (int i = 0; i < ImAxis_COUNT; ++i)
ApplyNextPlotData(i);
// capture scroll with a child region
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoChild)) {
ImVec2 child_size;
if (gp.CurrentSubplot != nullptr)
child_size = gp.CurrentSubplot->CellSize;
else
child_size = ImVec2(size.x == 0 ? gp.Style.PlotDefaultSize.x : size.x, size.y == 0 ? gp.Style.PlotDefaultSize.y : size.y);
ImGui::BeginChild(title_id, child_size, false, ImGuiWindowFlags_NoScrollbar);
Window = ImGui::GetCurrentWindow();
Window->ScrollMax.y = 1.0f;
gp.ChildWindowMade = true;
}
else {
gp.ChildWindowMade = false;
}
// clear text buffers
plot.ClearTextBuffer();
plot.SetTitle(title_id);
@@ -2451,7 +2431,7 @@ bool BeginPlot(const char* title_id, const ImVec2& size, ImPlotFlags flags) {
ResetCtxForNextPlot(GImPlot);
return false;
}
// setup items (or dont)
if (gp.CurrentItems == nullptr)
gp.CurrentItems = &plot.Items;
@@ -2570,7 +2550,7 @@ void SetupFinish() {
// (2) get y tick labels (needed for left/right pad)
for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {
ImPlotAxis& axis = plot.YAxis(i);
if (axis.WillRender() && axis.ShowDefaultTicks && plot_height > 0) {
if (axis.WillRender() && axis.ShowDefaultTicks) {
axis.Locator(axis.Ticker, axis.Range, plot_height, true, axis.Formatter, axis.FormatterData);
}
}
@@ -2583,7 +2563,7 @@ void SetupFinish() {
// (4) get x ticks
for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {
ImPlotAxis& axis = plot.XAxis(i);
if (axis.WillRender() && axis.ShowDefaultTicks && plot_width > 0) {
if (axis.WillRender() && axis.ShowDefaultTicks) {
axis.Locator(axis.Ticker, axis.Range, plot_width, false, axis.Formatter, axis.FormatterData);
}
}
@@ -2778,7 +2758,7 @@ void EndPlot() {
// FINAL RENDER -----------------------------------------------------------
const bool render_border = gp.Style.PlotBorderSize > 0 && GetStyleColorVec4(ImPlotCol_PlotBorder).w > 0;
const bool render_border = gp.Style.PlotBorderSize > 0 && gp.Style.Colors[ImPlotCol_PlotBorder].w > 0;
const bool any_x_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);
const bool any_y_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);
@@ -3043,57 +3023,24 @@ void EndPlot() {
legend.Location,
legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding);
legend.Rect = ImRect(legend_pos, legend_pos + legend_size);
legend.RectClamped = legend.Rect;
const bool legend_scrollable = ClampLegendRect(legend.RectClamped,
legend_out ? plot.FrameRect : plot.PlotRect,
legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding
);
const ImGuiButtonFlags legend_button_flags = ImGuiButtonFlags_AllowOverlap
| ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick
| ImGuiButtonFlags_MouseButtonLeft
| ImGuiButtonFlags_MouseButtonRight
| ImGuiButtonFlags_MouseButtonMiddle
| ImGuiButtonFlags_FlattenChildren;
ImGui::KeepAliveID(plot.Items.ID);
ImGui::ButtonBehavior(legend.RectClamped, plot.Items.ID, &legend.Hovered, &legend.Held, legend_button_flags);
legend.Hovered = legend.Hovered || (ImGui::IsWindowHovered() && legend.RectClamped.Contains(IO.MousePos));
if (legend_scrollable) {
if (legend.Hovered) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.Items.ID);
if (IO.MouseWheel != 0.0f) {
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
legend.Scroll.x += scroll_step * IO.MouseWheel;
legend.Scroll.y += scroll_step * IO.MouseWheel;
}
}
const ImVec2 min_scroll_offset = legend.RectClamped.GetSize() - legend.Rect.GetSize();
legend.Scroll.x = ImClamp(legend.Scroll.x, min_scroll_offset.x, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
const ImVec2 scroll_offset = legend_horz ? ImVec2(legend.Scroll.x, 0) : ImVec2(0, legend.Scroll.y);
ImVec2 legend_offset = legend.RectClamped.Min - legend.Rect.Min + scroll_offset;
legend.Rect.Min += legend_offset;
legend.Rect.Max += legend_offset;
} else {
legend.Scroll = ImVec2(0,0);
}
// test hover
legend.Hovered = ImGui::IsWindowHovered() && legend.Rect.Contains(IO.MousePos);
const ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
if (legend_out)
ImGui::PushClipRect(plot.FrameRect.Min, plot.FrameRect.Max, true);
else
PushPlotClipRect();
ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
DrawList.AddRectFilled(legend.Rect.Min, legend.Rect.Max, col_bg);
DrawList.AddRect(legend.Rect.Min, legend.Rect.Max, col_bd);
bool legend_contextable = ShowLegendEntries(plot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
DrawList.AddRect(legend.RectClamped.Min, legend.RectClamped.Max, col_bd);
ImGui::PopClipRect();
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
// main ctx menu
if (gp.OpenContextThisFrame && legend_contextable && !ImHasFlag(plot.Flags, ImPlotFlags_NoMenus))
ImGui::OpenPopup("##LegendContext");
ImGui::OpenPopup("##LegendContext");
ImGui::PopClipRect();
if (ImGui::BeginPopup("##LegendContext")) {
ImGui::Text("Legend"); ImGui::Separator();
if (ShowLegendContextMenu(legend, !ImHasFlag(plot.Flags, ImPlotFlags_NoLegend)))
@@ -3403,7 +3350,7 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
subplot.FrameRect = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);
subplot.GridRect.Min = subplot.FrameRect.Min + half_pad + ImVec2(0,pad_top);
subplot.GridRect.Max = subplot.FrameRect.Max - half_pad;
subplot.FrameHovered = subplot.FrameRect.Contains(ImGui::GetMousePos()) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows|ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
subplot.FrameHovered = subplot.FrameRect.Contains(ImGui::GetMousePos()) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows);
// outside legend adjustments (TODO: make function)
const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);
@@ -3450,7 +3397,7 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
ImGui::KeepAliveID(sep_id);
const ImRect sep_bb = ImRect(subplot.GridRect.Min.x, ypos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.x, ypos+SUBPLOT_SPLITTER_HALF_THICKNESS);
bool sep_hov = false, sep_hld = false;
const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);
const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);
if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) {
if (sep_clk && ImGui::IsMouseDoubleClicked(0)) {
float p = (subplot.RowRatios[r] + subplot.RowRatios[r+1])/2;
@@ -3480,7 +3427,7 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
ImGui::KeepAliveID(sep_id);
const ImRect sep_bb = ImRect(xpos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Min.y, xpos+SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.y);
bool sep_hov = false, sep_hld = false;
const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);
const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);
if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) {
if (sep_clk && ImGui::IsMouseDoubleClicked(0)) {
float p = (subplot.ColRatios[c] + subplot.ColRatios[c+1])/2;
@@ -3541,7 +3488,6 @@ void EndSubplots() {
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentSubplot != nullptr, "Mismatched BeginSubplots()/EndSubplots()!");
ImPlotSubplot& subplot = *gp.CurrentSubplot;
const ImGuiIO& IO = ImGui::GetIO();
// set alignments
for (int r = 0; r < subplot.Rows; ++r)
subplot.RowAlignmentData[r].End();
@@ -3560,60 +3506,24 @@ void EndSubplots() {
const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);
ImDrawList& DrawList = *ImGui::GetWindowDrawList();
if (share_items && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoLegend) && subplot.Items.GetLegendCount() > 0) {
ImPlotLegend& legend = subplot.Items.Legend;
const bool legend_horz = ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal);
const bool legend_horz = ImHasFlag(subplot.Items.Legend.Flags, ImPlotLegendFlags_Horizontal);
const ImVec2 legend_size = CalcLegendSize(subplot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz);
const ImVec2 legend_pos = GetLocationPos(subplot.FrameRect, legend_size, legend.Location, gp.Style.PlotPadding);
legend.Rect = ImRect(legend_pos, legend_pos + legend_size);
legend.RectClamped = legend.Rect;
const bool legend_scrollable = ClampLegendRect(legend.RectClamped,subplot.FrameRect, gp.Style.PlotPadding);
const ImGuiButtonFlags legend_button_flags = ImGuiButtonFlags_AllowOverlap
| ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick
| ImGuiButtonFlags_MouseButtonLeft
| ImGuiButtonFlags_MouseButtonRight
| ImGuiButtonFlags_MouseButtonMiddle
| ImGuiButtonFlags_FlattenChildren;
ImGui::KeepAliveID(subplot.Items.ID);
ImGui::ButtonBehavior(legend.RectClamped, subplot.Items.ID, &legend.Hovered, &legend.Held, legend_button_flags);
legend.Hovered = legend.Hovered || (subplot.FrameHovered && legend.RectClamped.Contains(ImGui::GetIO().MousePos));
if (legend_scrollable) {
if (legend.Hovered) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, subplot.Items.ID);
if (IO.MouseWheel != 0.0f) {
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
legend.Scroll.x += scroll_step * IO.MouseWheel;
legend.Scroll.y += scroll_step * IO.MouseWheel;
}
}
const ImVec2 min_scroll_offset = legend.RectClamped.GetSize() - legend.Rect.GetSize();
legend.Scroll.x = ImClamp(legend.Scroll.x, min_scroll_offset.x, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
const ImVec2 scroll_offset = legend_horz ? ImVec2(legend.Scroll.x, 0) : ImVec2(0, legend.Scroll.y);
ImVec2 legend_offset = legend.RectClamped.Min - legend.Rect.Min + scroll_offset;
legend.Rect.Min += legend_offset;
legend.Rect.Max += legend_offset;
} else {
legend.Scroll = ImVec2(0,0);
}
const ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
bool legend_contextable = ShowLegendEntries(subplot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
DrawList.AddRect(legend.RectClamped.Min, legend.RectClamped.Max, col_bd);
ImGui::PopClipRect();
const ImVec2 legend_pos = GetLocationPos(subplot.FrameRect, legend_size, subplot.Items.Legend.Location, gp.Style.PlotPadding);
subplot.Items.Legend.Rect = ImRect(legend_pos, legend_pos + legend_size);
subplot.Items.Legend.Hovered = subplot.FrameHovered && subplot.Items.Legend.Rect.Contains(ImGui::GetIO().MousePos);
ImGui::PushClipRect(subplot.FrameRect.Min, subplot.FrameRect.Max, true);
ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
DrawList.AddRectFilled(subplot.Items.Legend.Rect.Min, subplot.Items.Legend.Rect.Max, col_bg);
DrawList.AddRect(subplot.Items.Legend.Rect.Min, subplot.Items.Legend.Rect.Max, col_bd);
bool legend_contextable = ShowLegendEntries(subplot.Items, subplot.Items.Legend.Rect, subplot.Items.Legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(subplot.Items.Legend.Flags, ImPlotLegendFlags_NoMenus);
if (legend_contextable && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoMenus) && ImGui::GetIO().MouseReleased[gp.InputMap.Menu])
ImGui::OpenPopup("##LegendContext");
ImGui::PopClipRect();
if (ImGui::BeginPopup("##LegendContext")) {
ImGui::Text("Legend"); ImGui::Separator();
if (ShowLegendContextMenu(legend, !ImHasFlag(subplot.Flags, ImPlotFlags_NoLegend)))
if (ShowLegendContextMenu(subplot.Items.Legend, !ImHasFlag(subplot.Flags, ImPlotFlags_NoLegend)))
ImFlipFlag(subplot.Flags, ImPlotFlags_NoLegend);
ImGui::EndPopup();
}
@@ -3894,7 +3804,7 @@ IMPLOT_API void TagYV(double y, const ImVec4& color, const char* fmt, va_list ar
static const float DRAG_GRAB_HALF_SIZE = 4.0f;
bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) {
bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius, ImPlotDragToolFlags flags) {
ImGui::PushID("#IMPLOT_DRAG_POINT");
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "DragPoint() needs to be called between BeginPlot() and EndPlot()!");
SetupLock();
@@ -3916,34 +3826,30 @@ bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius,
bool hovered = false, held = false;
ImGui::KeepAliveID(id);
if (input) {
bool clicked = ImGui::ButtonBehavior(rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if (input)
ImGui::ButtonBehavior(rect,id,&hovered,&held);
bool modified = false;
bool dragging = false;
if (held && ImGui::IsMouseDragging(0)) {
*x = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
*y = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
modified = true;
dragging = true;
}
PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList();
if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
if (modified && no_delay)
if (dragging && no_delay)
pos = PlotToPixels(*x,*y,IMPLOT_AUTO,IMPLOT_AUTO);
DrawList.AddCircleFilled(pos, radius, col32);
PopPlotClipRect();
ImGui::PopID();
return modified;
return dragging;
}
bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) {
bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags) {
// ImGui::PushID("#IMPLOT_DRAG_LINE_X");
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "DragLineX() needs to be called between BeginPlot() and EndPlot()!");
@@ -3965,12 +3871,8 @@ bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPl
bool hovered = false, held = false;
ImGui::KeepAliveID(id);
if (input) {
bool clicked = ImGui::ButtonBehavior(rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if (input)
ImGui::ButtonBehavior(rect,id,&hovered,&held);
if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
@@ -3979,15 +3881,15 @@ bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPl
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
bool modified = false;
bool dragging = false;
if (held && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
modified = true;
dragging = true;
}
PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList();
if (modified && no_delay)
if (dragging && no_delay)
x = IM_ROUND(PlotToPixels(*value,0,IMPLOT_AUTO,IMPLOT_AUTO).x);
DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yb), col32, thickness);
DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yt+len), col32, 3*thickness);
@@ -3995,10 +3897,10 @@ bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPl
PopPlotClipRect();
// ImGui::PopID();
return modified;
return dragging;
}
bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) {
bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags) {
ImGui::PushID("#IMPLOT_DRAG_LINE_Y");
ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "DragLineY() needs to be called between BeginPlot() and EndPlot()!");
@@ -4021,12 +3923,8 @@ bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPl
bool hovered = false, held = false;
ImGui::KeepAliveID(id);
if (input) {
bool clicked = ImGui::ButtonBehavior(rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if (input)
ImGui::ButtonBehavior(rect,id,&hovered,&held);
if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
@@ -4035,15 +3933,15 @@ bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPl
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
bool modified = false;
bool dragging = false;
if (held && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
modified = true;
dragging = true;
}
PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList();
if (modified && no_delay)
if (dragging && no_delay)
y = IM_ROUND(PlotToPixels(0, *value,IMPLOT_AUTO,IMPLOT_AUTO).y);
DrawList.AddLine(ImVec2(xl,y), ImVec2(xr,y), col32, thickness);
DrawList.AddLine(ImVec2(xl,y), ImVec2(xl+len,y), col32, 3*thickness);
@@ -4051,10 +3949,10 @@ bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPl
PopPlotClipRect();
ImGui::PopID();
return modified;
return dragging;
}
bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_max, const ImVec4& col, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) {
bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_max, const ImVec4& col, ImPlotDragToolFlags flags) {
ImGui::PushID("#IMPLOT_DRAG_RECT");
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "DragRect() needs to be called between BeginPlot() and EndPlot()!");
SetupLock();
@@ -4091,18 +3989,13 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
ImU32 col32_a = ImGui::ColorConvertFloat4ToU32(color);
const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id);
bool modified = false;
bool clicked = false, hovered = false, held = false;
bool dragging = false;
bool hovered = false, held = false;
ImRect b_rect(pc.x-DRAG_GRAB_HALF_SIZE,pc.y-DRAG_GRAB_HALF_SIZE,pc.x+DRAG_GRAB_HALF_SIZE,pc.y+DRAG_GRAB_HALF_SIZE);
ImGui::KeepAliveID(id);
if (input) {
// middle point
clicked = ImGui::ButtonBehavior(b_rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if (input)
ImGui::ButtonBehavior(b_rect,id,&hovered,&held);
if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
@@ -4112,7 +4005,7 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
*y[i] = pp.y;
*x[i] = pp.x;
}
modified = true;
dragging = true;
}
for (int i = 0; i < 4; ++i) {
@@ -4120,19 +4013,15 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
b_rect = ImRect(p[i].x-DRAG_GRAB_HALF_SIZE,p[i].y-DRAG_GRAB_HALF_SIZE,p[i].x+DRAG_GRAB_HALF_SIZE,p[i].y+DRAG_GRAB_HALF_SIZE);
ImGuiID p_id = id + i + 1;
ImGui::KeepAliveID(p_id);
if (input) {
clicked = ImGui::ButtonBehavior(b_rect,p_id,&hovered,&held);
if (out_clicked) *out_clicked = *out_clicked || clicked;
if (out_hovered) *out_hovered = *out_hovered || hovered;
if (out_held) *out_held = *out_held || held;
}
if (input)
ImGui::ButtonBehavior(b_rect,p_id,&hovered,&held);
if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(cur[i]);
if (held && ImGui::IsMouseDragging(0)) {
*x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
*y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
modified = true;
dragging = true;
}
// edges
@@ -4142,12 +4031,8 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
: ImRect(e_min.x - DRAG_GRAB_HALF_SIZE, e_min.y + DRAG_GRAB_HALF_SIZE, e_max.x + DRAG_GRAB_HALF_SIZE, e_max.y - DRAG_GRAB_HALF_SIZE);
ImGuiID e_id = id + i + 5;
ImGui::KeepAliveID(e_id);
if (input) {
clicked = ImGui::ButtonBehavior(b_rect,e_id,&hovered,&held);
if (out_clicked) *out_clicked = *out_clicked || clicked;
if (out_hovered) *out_hovered = *out_hovered || hovered;
if (out_held) *out_held = *out_held || held;
}
if (input)
ImGui::ButtonBehavior(b_rect,e_id,&hovered,&held);
if ((hovered || held) && show_curs)
h[i] ? ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS) : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
if (held && ImGui::IsMouseDragging(0)) {
@@ -4155,7 +4040,7 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
*y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
else
*x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
modified = true;
dragging = true;
}
if (hovered && ImGui::IsMouseDoubleClicked(0))
{
@@ -4164,22 +4049,14 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
*y[i] = ((y[i] == y_min && *y_min < *y_max) || (y[i] == y_max && *y_max < *y_min)) ? b.Y.Min : b.Y.Max;
else
*x[i] = ((x[i] == x_min && *x_min < *x_max) || (x[i] == x_max && *x_max < *x_min)) ? b.X.Min : b.X.Max;
modified = true;
dragging = true;
}
}
const bool mouse_inside = rect_grab.Contains(ImGui::GetMousePos());
const bool mouse_clicked = ImGui::IsMouseClicked(0);
const bool mouse_down = ImGui::IsMouseDown(0);
if (input && mouse_inside) {
if (out_clicked) *out_clicked = *out_clicked || mouse_clicked;
if (out_hovered) *out_hovered = true;
if (out_held) *out_held = *out_held || mouse_down;
}
PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList();
if (modified && no_delay) {
if (dragging && no_delay) {
for (int i = 0; i < 4; ++i)
p[i] = PlotToPixels(*x[i],*y[i],IMPLOT_AUTO,IMPLOT_AUTO);
pc = PlotToPixels((*x_min+*x_max)/2,(*y_min+*y_max)/2,IMPLOT_AUTO,IMPLOT_AUTO);
@@ -4187,18 +4064,18 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
}
DrawList.AddRectFilled(rect.Min, rect.Max, col32_a);
DrawList.AddRect(rect.Min, rect.Max, col32);
if (input && (modified || mouse_inside)) {
if (input && (dragging || rect_grab.Contains(ImGui::GetMousePos()))) {
DrawList.AddCircleFilled(pc,DRAG_GRAB_HALF_SIZE,col32);
for (int i = 0; i < 4; ++i)
DrawList.AddCircleFilled(p[i],DRAG_GRAB_HALF_SIZE,col32);
}
PopPlotClipRect();
ImGui::PopID();
return modified;
return dragging;
}
bool DragRect(int id, ImPlotRect* bounds, const ImVec4& col, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) {
return DragRect(id, &bounds->X.Min, &bounds->Y.Min,&bounds->X.Max, &bounds->Y.Max, col, flags, out_clicked, out_hovered, out_held);
bool DragRect(int id, ImPlotRect* bounds, const ImVec4& col, ImPlotDragToolFlags flags) {
return DragRect(id, &bounds->X.Min, &bounds->Y.Min,&bounds->X.Max, &bounds->Y.Max, col, flags);
}
//-----------------------------------------------------------------------------
@@ -4294,7 +4171,7 @@ bool BeginDragDropTargetAxis(ImAxis axis) {
bool BeginDragDropTargetLegend() {
SetupLock();
ImPlotItemGroup& items = *GImPlot->CurrentItems;
ImRect rect = items.Legend.RectClamped;
ImRect rect = items.Legend.Rect;
return ImGui::BeginDragDropTargetCustom(rect, items.ID);
}
@@ -5233,7 +5110,6 @@ void ShowMetricsWindow(bool* p_popen) {
static bool show_frame_rects = false;
static bool show_subplot_frame_rects = false;
static bool show_subplot_grid_rects = false;
static bool show_legend_rects = false;
ImDrawList& fg = *ImGui::GetForegroundDrawList();
@@ -5258,7 +5134,6 @@ void ShowMetricsWindow(bool* p_popen) {
ImGui::Checkbox("Show Axis Rects", &show_axis_rects);
ImGui::Checkbox("Show Subplot Frame Rects", &show_subplot_frame_rects);
ImGui::Checkbox("Show Subplot Grid Rects", &show_subplot_grid_rects);
ImGui::Checkbox("Show Legend Rects", &show_legend_rects);
ImGui::TreePop();
}
const int n_plots = gp.Plots.GetBufSize();
@@ -5280,10 +5155,6 @@ void ShowMetricsWindow(bool* p_popen) {
fg.AddRect(plot->Axes[i].HoverRect.Min, plot->Axes[i].HoverRect.Max, IM_COL32(0,255,0,255));
}
}
if (show_legend_rects && plot->Items.GetLegendCount() > 0) {
fg.AddRect(plot->Items.Legend.Rect.Min, plot->Items.Legend.Rect.Max, IM_COL32(255,192,0,255));
fg.AddRect(plot->Items.Legend.RectClamped.Min, plot->Items.Legend.RectClamped.Max, IM_COL32(255,128,0,255));
}
}
for (int p = 0; p < n_subplots; ++p) {
ImPlotSubplot* subplot = gp.Subplots.GetByIndex(p);
@@ -5291,10 +5162,6 @@ void ShowMetricsWindow(bool* p_popen) {
fg.AddRect(subplot->FrameRect.Min, subplot->FrameRect.Max, IM_COL32(255,0,0,255));
if (show_subplot_grid_rects)
fg.AddRect(subplot->GridRect.Min, subplot->GridRect.Max, IM_COL32(0,0,255,255));
if (show_legend_rects && subplot->Items.GetLegendCount() > 0) {
fg.AddRect(subplot->Items.Legend.Rect.Min, subplot->Items.Legend.Rect.Max, IM_COL32(255,192,0,255));
fg.AddRect(subplot->Items.Legend.RectClamped.Min, subplot->Items.Legend.RectClamped.Max, IM_COL32(255,128,0,255));
}
}
if (ImGui::TreeNode("Plots","Plots (%d)", n_plots)) {
for (int p = 0; p < n_plots; ++p) {

View File

@@ -1,6 +1,6 @@
// MIT License
// Copyright (c) 2023 Evan Pezent
// Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.17
// ImPlot v0.14
// We define this so that the demo does not accidentally use deprecated API
#ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS
@@ -610,8 +610,10 @@ void Demo_PieCharts() {
static ImPlotPieChartFlags flags = 0;
ImGui::SetNextItemWidth(250);
ImGui::DragFloat4("Values", data1, 0.01f, 0, 1);
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Normalize);
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_IgnoreHidden);
if ((data1[0] + data1[1] + data1[2] + data1[3]) < 1) {
ImGui::SameLine();
CHECKBOX_FLAG(flags,ImPlotPieChartFlags_Normalize);
}
if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
@@ -1145,7 +1147,7 @@ void Demo_MultipleAxes() {
ImPlot::SetAxes(ImAxis_X1, ImAxis_Y2);
ImPlot::PlotLine("f(x) = cos(x)*.2+.5", xs, ys2, 1001);
}
if (x2_axis && y3_axis) {
if (y3_axis) {
ImPlot::SetAxes(ImAxis_X2, ImAxis_Y3);
ImPlot::PlotLine("f(x) = sin(x+.5)*100+200 ", xs2, ys3, 1001);
}
@@ -1262,7 +1264,7 @@ ImPlotPoint SinewaveGetter(int i, void* data) {
void Demo_SubplotsSizing() {
static ImPlotSubplotFlags flags = ImPlotSubplotFlags_ShareItems|ImPlotSubplotFlags_NoLegend;
static ImPlotSubplotFlags flags = ImPlotSubplotFlags_None;
ImGui::CheckboxFlags("ImPlotSubplotFlags_NoResize", (unsigned int*)&flags, ImPlotSubplotFlags_NoResize);
ImGui::CheckboxFlags("ImPlotSubplotFlags_NoTitle", (unsigned int*)&flags, ImPlotSubplotFlags_NoTitle);
@@ -1270,26 +1272,17 @@ void Demo_SubplotsSizing() {
static int cols = 3;
ImGui::SliderInt("Rows",&rows,1,5);
ImGui::SliderInt("Cols",&cols,1,5);
if (rows < 1 || cols < 1) {
ImGui::TextColored(ImVec4(1,0,0,1), "Nice try, but the number of rows and columns must be greater than 0!");
return;
}
static float rratios[] = {5,1,1,1,1,1};
static float cratios[] = {5,1,1,1,1,1};
ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,nullptr);
ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,nullptr);
if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) {
int id = 0;
for (int i = 0; i < rows*cols; ++i) {
if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) {
ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
float fi = 0.01f * (i+1);
if (rows*cols > 1) {
ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet));
}
char label[16];
snprintf(label, sizeof(label), "data%d", id++);
ImPlot::PlotLineG(label,SinewaveGetter,&fi,1000);
ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet));
ImPlot::PlotLineG("data",SinewaveGetter,&fi,1000);
ImPlot::EndPlot();
}
}
@@ -1309,7 +1302,6 @@ void Demo_SubplotItemSharing() {
static int id[] = {0,1,2,3,4,5};
static int curj = -1;
if (ImPlot::BeginSubplots("##ItemSharing", rows, cols, ImVec2(-1,400), flags)) {
ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Sort|ImPlotLegendFlags_Horizontal);
for (int i = 0; i < rows*cols; ++i) {
if (ImPlot::BeginPlot("")) {
float fc = 0.01f;
@@ -1384,9 +1376,6 @@ void Demo_LegendOptions() {
ImGui::SliderFloat2("LegendInnerPadding", (float*)&GetStyle().LegendInnerPadding, 0.0f, 10.0f, "%.0f");
ImGui::SliderFloat2("LegendSpacing", (float*)&GetStyle().LegendSpacing, 0.0f, 5.0f, "%.0f");
static int num_dummy_items = 25;
ImGui::SliderInt("Num Dummy Items (Demo Scrolling)", &num_dummy_items, 0, 100);
if (ImPlot::BeginPlot("##Legend",ImVec2(-1,0))) {
ImPlot::SetupLegend(loc, flags);
static MyImPlot::WaveData data1(0.001, 0.2, 4, 0.2);
@@ -1395,21 +1384,16 @@ void Demo_LegendOptions() {
static MyImPlot::WaveData data4(0.001, 0.2, 4, 0.8);
static MyImPlot::WaveData data5(0.001, 0.2, 4, 1.0);
ImPlot::PlotLineG("Item 002", MyImPlot::SawWave, &data1, 1000); // "Item B" added to legend
ImPlot::PlotLineG("Item 001##IDText", MyImPlot::SawWave, &data2, 1000); // "Item A" added to legend, text after ## used for ID only
ImPlot::PlotLineG("Item B", MyImPlot::SawWave, &data1, 1000); // "Item B" added to legend
ImPlot::PlotLineG("Item A##IDText", MyImPlot::SawWave, &data2, 1000); // "Item A" added to legend, text after ## used for ID only
ImPlot::PlotLineG("##NotListed", MyImPlot::SawWave, &data3, 1000); // plotted, but not added to legend
ImPlot::PlotLineG("Item 003", MyImPlot::SawWave, &data4, 1000); // "Item C" added to legend
ImPlot::PlotLineG("Item 003", MyImPlot::SawWave, &data5, 1000); // combined with previous "Item C"
ImPlot::PlotLineG("Item C", MyImPlot::SawWave, &data4, 1000); // "Item C" added to legend
ImPlot::PlotLineG("Item C", MyImPlot::SawWave, &data5, 1000); // combined with previous "Item C"
for (int i = 0; i < num_dummy_items; ++i) {
char label[16];
snprintf(label, sizeof(label), "Item %03d", i+4);
ImPlot::PlotDummy(label);
}
ImPlot::EndPlot();
}
}
}
//-----------------------------------------------------------------------------
void Demo_DragPoints() {
@@ -1419,18 +1403,15 @@ void Demo_DragPoints() {
ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();
ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);
ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks;
bool clicked[4] = {false, false, false, false};
bool hovered[4] = {false, false, false, false};
bool held[4] = {false, false, false, false};
if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(nullptr,nullptr,ax_flags,ax_flags);
ImPlot::SetupAxesLimits(0,1,0,1);
static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)};
ImPlot::DragPoint(0,&P[0].x,&P[0].y, ImVec4(0,0.9f,0,1),4,flags, &clicked[0], &hovered[0], &held[0]);
ImPlot::DragPoint(1,&P[1].x,&P[1].y, ImVec4(1,0.5f,1,1),4,flags, &clicked[1], &hovered[1], &held[1]);
ImPlot::DragPoint(2,&P[2].x,&P[2].y, ImVec4(0,0.5f,1,1),4,flags, &clicked[2], &hovered[2], &held[2]);
ImPlot::DragPoint(3,&P[3].x,&P[3].y, ImVec4(0,0.9f,0,1),4,flags, &clicked[3], &hovered[3], &held[3]);
ImPlot::DragPoint(0,&P[0].x,&P[0].y, ImVec4(0,0.9f,0,1),4,flags);
ImPlot::DragPoint(1,&P[1].x,&P[1].y, ImVec4(1,0.5f,1,1),4,flags);
ImPlot::DragPoint(2,&P[2].x,&P[2].y, ImVec4(0,0.5f,1,1),4,flags);
ImPlot::DragPoint(3,&P[3].x,&P[3].y, ImVec4(0,0.9f,0,1),4,flags);
static ImPlotPoint B[100];
for (int i = 0; i < 100; ++i) {
@@ -1443,12 +1424,14 @@ void Demo_DragPoints() {
B[i] = ImPlotPoint(w1*P[0].x + w2*P[1].x + w3*P[2].x + w4*P[3].x, w1*P[0].y + w2*P[1].y + w3*P[2].y + w4*P[3].y);
}
ImPlot::SetNextLineStyle(ImVec4(1,0.5f,1,1),hovered[1]||held[1] ? 2.0f : 1.0f);
ImPlot::SetNextLineStyle(ImVec4(1,0.5f,1,1));
ImPlot::PlotLine("##h1",&P[0].x, &P[0].y, 2, 0, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(ImVec4(0,0.5f,1,1), hovered[2]||held[2] ? 2.0f : 1.0f);
ImPlot::SetNextLineStyle(ImVec4(0,0.5f,1,1));
ImPlot::PlotLine("##h2",&P[2].x, &P[2].y, 2, 0, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(ImVec4(0,0.9f,0,1), hovered[0]||held[0]||hovered[3]||held[3] ? 3.0f : 2.0f);
ImPlot::SetNextLineStyle(ImVec4(0,0.9f,0,1), 2);
ImPlot::PlotLine("##bez",&B[0].x, &B[0].y, 100, 0, 0, sizeof(ImPlotPoint));
ImPlot::EndPlot();
}
}
@@ -1462,9 +1445,6 @@ void Demo_DragLines() {
static double y1 = 0.25;
static double y2 = 0.75;
static double f = 0.1;
bool clicked = false;
bool hovered = false;
bool held = false;
static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;
ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();
ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();
@@ -1480,9 +1460,8 @@ void Demo_DragLines() {
xs[i] = (x2+x1)/2+fabs(x2-x1)*(i/1000.0f - 0.5f);
ys[i] = (y1+y2)/2+fabs(y2-y1)/2*sin(f*i/10);
}
ImPlot::DragLineY(120482,&f,ImVec4(1,0.5f,1,1),1,flags, &clicked, &hovered, &held);
ImPlot::SetNextLineStyle(IMPLOT_AUTO_COL, hovered||held ? 2.0f : 1.0f);
ImPlot::PlotLine("Interactive Data", xs, ys, 1000);
ImPlot::DragLineY(120482,&f,ImVec4(1,0.5f,1,1),1,flags);
ImPlot::EndPlot();
}
}
@@ -1497,9 +1476,6 @@ void Demo_DragRects() {
static float y_data3[512];
static float sampling_freq = 44100;
static float freq = 500;
bool clicked = false;
bool hovered = false;
bool held = false;
for (size_t i = 0; i < 512; ++i) {
const float t = i / sampling_freq;
x_data[i] = t;
@@ -1509,7 +1485,6 @@ void Demo_DragRects() {
y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f;
}
ImGui::BulletText("Click and drag the edges, corners, and center of the rect.");
ImGui::BulletText("Double click edges to expand rect to plot extents.");
static ImPlotRect rect(0.0025,0.0045,0,0.5);
static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;
ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();
@@ -1522,11 +1497,9 @@ void Demo_DragRects() {
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
ImPlot::DragRect(0,&rect.X.Min,&rect.Y.Min,&rect.X.Max,&rect.Y.Max,ImVec4(1,0,1,1),flags, &clicked, &hovered, &held);
ImPlot::DragRect(0,&rect.X.Min,&rect.Y.Min,&rect.X.Max,&rect.Y.Max,ImVec4(1,0,1,1),flags);
ImPlot::EndPlot();
}
ImVec4 bg_col = held ? ImVec4(0.5f,0,0.5f,1) : (hovered ? ImVec4(0.25f,0,0.25f,1) : ImPlot::GetStyle().Colors[ImPlotCol_PlotBg]);
ImPlot::PushStyleColor(ImPlotCol_PlotBg, bg_col);
if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always);
@@ -1535,8 +1508,6 @@ void Demo_DragRects() {
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
ImPlot::EndPlot();
}
ImPlot::PopStyleColor();
ImGui::Text("Rect is %sclicked, %shovered, %sheld", clicked ? "" : "not ", hovered ? "" : "not ", held ? "" : "not ");
}
//-----------------------------------------------------------------------------
@@ -2328,7 +2299,7 @@ ImPlotPoint Spiral(int idx, void*) {
void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) {
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0));
if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly)) {
if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) {
ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always);
ImPlot::SetNextLineStyle(col);

View File

@@ -1,6 +1,6 @@
// MIT License
// Copyright (c) 2023 Evan Pezent
// Copyright (c) 2020 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ImPlot v0.17
// ImPlot v0.14
#define IMGUI_DEFINE_MATH_OPERATORS
#include "implot.h"
@@ -98,11 +98,11 @@ static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); }
#define _CAT(x, y) _CAT_(x, y)
#define _CAT_(x,y) x ## y
#define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END)
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_2
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_1
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_2
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_1
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1_END
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2_END
#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES)
#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES);
namespace ImPlot {
@@ -1287,7 +1287,7 @@ struct RendererShaded : RendererBase {
return false;
}
const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y);
const ImVec2 intersection = intersect == 0 ? ImVec2(0,0) : Intersection(P11,P21,P12,P22);
ImVec2 intersection = Intersection(P11,P21,P12,P22);
draw_list._VtxWritePtr[0].pos = P11;
draw_list._VtxWritePtr[0].uv = UV;
draw_list._VtxWritePtr[0].col = Col;
@@ -1569,10 +1569,6 @@ void RenderMarkers(const _Getter& getter, ImPlotMarker marker, float size, bool
template <typename _Getter>
void PlotLineEx(const char* label_id, const _Getter& getter, ImPlotLineFlags flags) {
if (BeginItemEx(label_id, Fitter1<_Getter>(getter), flags, ImPlotCol_Line)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
if (getter.Count > 1) {
if (ImHasFlag(flags, ImPlotLineFlags_Shaded) && s.RenderFill) {
@@ -1644,10 +1640,6 @@ void PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int c
template <typename Getter>
void PlotScatterEx(const char* label_id, const Getter& getter, ImPlotScatterFlags flags) {
if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_MarkerOutline)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle: s.Marker;
if (marker != ImPlotMarker_None) {
@@ -1694,12 +1686,8 @@ void PlotScatterG(const char* label_id, ImPlotGetter getter_func, void* data, in
template <typename Getter>
void PlotStairsEx(const char* label_id, const Getter& getter, ImPlotStairsFlags flags) {
if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_Line)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
if (getter.Count > 1) {
if (getter.Count > 1 ) {
if (s.RenderFill && ImHasFlag(flags,ImPlotStairsFlags_Shaded)) {
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
if (ImHasFlag(flags, ImPlotStairsFlags_PreStep))
@@ -1758,10 +1746,6 @@ void PlotStairsG(const char* label_id, ImPlotGetter getter_func, void* data, int
template <typename Getter1, typename Getter2>
void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) {
if (BeginItemEx(label_id, Fitter2<Getter1,Getter2>(getter1,getter2), flags, ImPlotCol_Fill)) {
if (getter1.Count <= 0 || getter2.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
if (s.RenderFill) {
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
@@ -1822,10 +1806,6 @@ void PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, I
template <typename Getter1, typename Getter2>
void PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 getter2, double width, ImPlotBarsFlags flags) {
if (BeginItemEx(label_id, FitterBarV<Getter1,Getter2>(getter1,getter2,width), flags, ImPlotCol_Fill)) {
if (getter1.Count <= 0 || getter2.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
@@ -1846,10 +1826,6 @@ void PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 get
template <typename Getter1, typename Getter2>
void PlotBarsHEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, double height, ImPlotBarsFlags flags) {
if (BeginItemEx(label_id, FitterBarH<Getter1,Getter2>(getter1,getter2,height), flags, ImPlotCol_Fill)) {
if (getter1.Count <= 0 || getter2.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
@@ -2006,10 +1982,6 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
template <typename _GetterPos, typename _GetterNeg>
void PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) {
if (getter_pos.Count <= 0 || getter_neg.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
ImDrawList& draw_list = *GetPlotDrawList();
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
@@ -2031,10 +2003,6 @@ void PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const
template <typename _GetterPos, typename _GetterNeg>
void PlotErrorBarsHEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) {
if (getter_pos.Count <= 0 || getter_neg.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
ImDrawList& draw_list = *GetPlotDrawList();
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
@@ -2092,17 +2060,13 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
//-----------------------------------------------------------------------------
template <typename _GetterM, typename _GetterB>
void PlotStemsEx(const char* label_id, const _GetterM& getter_mark, const _GetterB& getter_base, ImPlotStemsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterM,_GetterB>(getter_mark,getter_base), flags, ImPlotCol_Line)) {
if (getter_mark.Count <= 0 || getter_base.Count <= 0) {
EndItem();
return;
}
void PlotStemsEx(const char* label_id, const _GetterM& get_mark, const _GetterB& get_base, ImPlotStemsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterM,_GetterB>(get_mark,get_base), flags, ImPlotCol_Line)) {
const ImPlotNextItemData& s = GetItemData();
// render stems
if (s.RenderLine) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
RenderPrimitives2<RendererLineSegments2>(getter_mark, getter_base, col_line, s.LineWeight);
RenderPrimitives2<RendererLineSegments2>(get_mark, get_base, col_line, s.LineWeight);
}
// render markers
if (s.Marker != ImPlotMarker_None) {
@@ -2110,7 +2074,7 @@ void PlotStemsEx(const char* label_id, const _GetterM& getter_mark, const _Gette
PushPlotClipRect(s.MarkerSize);
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
RenderMarkers<_GetterM>(getter_mark, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);
RenderMarkers<_GetterM>(get_mark, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);
}
EndItem();
}
@@ -2159,17 +2123,13 @@ template <typename T>
void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags, int offset, int stride) {
const ImPlotRect lims = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO);
if (ImHasFlag(flags, ImPlotInfLinesFlags_Horizontal)) {
GetterXY<IndexerConst,IndexerIdx<T>> getter_min(IndexerConst(lims.X.Min),IndexerIdx<T>(values,count,offset,stride),count);
GetterXY<IndexerConst,IndexerIdx<T>> getter_max(IndexerConst(lims.X.Max),IndexerIdx<T>(values,count,offset,stride),count);
if (BeginItemEx(label_id, FitterY<GetterXY<IndexerConst,IndexerIdx<T>>>(getter_min), flags, ImPlotCol_Line)) {
if (count <= 0) {
EndItem();
return;
}
GetterXY<IndexerConst,IndexerIdx<T>> get_min(IndexerConst(lims.X.Min),IndexerIdx<T>(values,count,offset,stride),count);
GetterXY<IndexerConst,IndexerIdx<T>> get_max(IndexerConst(lims.X.Max),IndexerIdx<T>(values,count,offset,stride),count);
if (BeginItemEx(label_id, FitterY<GetterXY<IndexerConst,IndexerIdx<T>>>(get_min), flags, ImPlotCol_Line)) {
const ImPlotNextItemData& s = GetItemData();
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
if (s.RenderLine)
RenderPrimitives2<RendererLineSegments2>(getter_min, getter_max, col_line, s.LineWeight);
RenderPrimitives2<RendererLineSegments2>(get_min, get_max, col_line, s.LineWeight);
EndItem();
}
}
@@ -2177,10 +2137,6 @@ void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLin
GetterXY<IndexerIdx<T>,IndexerConst> get_min(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Min),count);
GetterXY<IndexerIdx<T>,IndexerConst> get_max(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Max),count);
if (BeginItemEx(label_id, FitterX<GetterXY<IndexerIdx<T>,IndexerConst>>(get_min), flags, ImPlotCol_Line)) {
if (count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData();
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
if (s.RenderLine)
@@ -2216,121 +2172,57 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent
}
template <typename T>
double PieChartSum(const T* values, int count, bool ignore_hidden) {
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & draw_list = *GetPlotDrawList();
double sum = 0;
if (ignore_hidden) {
ImPlotContext& gp = *GImPlot;
ImPlotItemGroup& Items = *gp.CurrentItems;
for (int i = 0; i < count; ++i) {
if (i >= Items.GetItemCount())
break;
ImPlotItem* item = Items.GetItemByIndex(i);
IM_ASSERT(item != nullptr);
if (item->Show) {
sum += (double)values[i];
}
}
}
else {
for (int i = 0; i < count; ++i) {
sum += (double)values[i];
}
}
return sum;
}
template <typename T>
void PlotPieChartEx(const char* const label_ids[], const T* values, int count, ImPlotPoint center, double radius, double angle0, ImPlotPieChartFlags flags) {
ImDrawList& draw_list = *GetPlotDrawList();
const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden);
const double sum = PieChartSum(values, count, ignore_hidden);
const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0;
for (int i = 0; i < count; ++i)
sum += (double)values[i];
const bool normalize = ImHasFlag(flags,ImPlotPieChartFlags_Normalize) || sum > 1.0;
ImPlotPoint center(x,y);
PushPlotClipRect();
double a0 = angle0 * 2 * IM_PI / 360.0;
double a1 = angle0 * 2 * IM_PI / 360.0;
ImPlotPoint Pmin = ImPlotPoint(center.x - radius, center.y - radius);
ImPlotPoint Pmax = ImPlotPoint(center.x + radius, center.y + radius);
ImPlotPoint Pmin = ImPlotPoint(x-radius,y-radius);
ImPlotPoint Pmax = ImPlotPoint(x+radius,y+radius);
for (int i = 0; i < count; ++i) {
ImPlotItem* item = GetItem(label_ids[i]);
const double percent = normalize ? (double)values[i] / sum : (double)values[i];
const bool skip = sum <= 0.0 || (ignore_hidden && item != nullptr && !item->Show);
if (!skip)
a1 = a0 + 2 * IM_PI * percent;
if (BeginItemEx(label_ids[i], FitterRect(Pmin, Pmax))) {
if (sum > 0.0) {
ImU32 col = GetCurrentItem()->Color;
if (percent < 0.5) {
RenderPieSlice(draw_list, center, radius, a0, a1, col);
}
else {
RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
}
double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent;
if (BeginItemEx(label_ids[i], FitterRect(Pmin,Pmax))) {
ImU32 col = GetCurrentItem()->Color;
if (percent < 0.5) {
RenderPieSlice(draw_list, center, radius, a0, a1, col);
}
else {
RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
}
EndItem();
}
if (!skip)
a0 = a1;
a0 = a1;
}
}
int PieChartFormatter(double value, char* buff, int size, void* data) {
const char* fmt = (const char*)data;
return snprintf(buff, size, fmt, value);
};
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
PlotPieChart<T>(label_ids, values, count, x, y, radius, PieChartFormatter, (void*)fmt, angle0, flags);
}
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList& draw_list = *GetPlotDrawList();
const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden);
const double sum = PieChartSum(values, count, ignore_hidden);
const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0;
ImPlotPoint center(x, y);
PushPlotClipRect();
PlotPieChartEx(label_ids, values, count, center, radius, angle0, flags);
if (fmt != nullptr) {
double a0 = angle0 * 2 * IM_PI / 360.0;
double a1 = angle0 * 2 * IM_PI / 360.0;
a0 = angle0 * 2 * IM_PI / 360.0;
a1 = angle0 * 2 * IM_PI / 360.0;
char buffer[32];
for (int i = 0; i < count; ++i) {
ImPlotItem* item = GetItem(label_ids[i]);
IM_ASSERT(item != nullptr);
const double percent = normalize ? (double)values[i] / sum : (double)values[i];
const bool skip = ignore_hidden && item != nullptr && !item->Show;
if (!skip) {
a1 = a0 + 2 * IM_PI * percent;
if (item->Show) {
fmt((double)values[i], buffer, 32, fmt_data);
ImVec2 size = ImGui::CalcTextSize(buffer);
double angle = a0 + (a1 - a0) * 0.5;
ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO);
ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
draw_list.AddText(pos - size * 0.5f, col, buffer);
}
a0 = a1;
double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent;
if (item->Show) {
ImFormatString(buffer, 32, fmt, (double)values[i]);
ImVec2 size = ImGui::CalcTextSize(buffer);
double angle = a0 + (a1 - a0) * 0.5;
ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle),IMPLOT_AUTO,IMPLOT_AUTO);
ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
draw_list.AddText(pos - size * 0.5f, col, buffer);
}
a0 = a1;
}
}
PopPlotClipRect();
}
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags);
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO
@@ -2391,8 +2283,8 @@ struct GetterHeatmapColMaj {
{ }
template <typename I> IMPLOT_INLINE RectC operator()(I idx) const {
double val = (double)Values[idx];
const int r = idx % Rows;
const int c = idx / Rows;
const int r = idx % Cols;
const int c = idx / Cols;
const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));
RectC rect;
rect.Pos = p;
@@ -2483,10 +2375,6 @@ void RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, d
template <typename T>
void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags) {
if (BeginItemEx(label_id, FitterRect(bounds_min, bounds_max))) {
if (rows <= 0 || cols <= 0) {
EndItem();
return;
}
ImDrawList& draw_list = *GetPlotDrawList();
const bool col_maj = ImHasFlag(flags, ImPlotHeatmapFlags_ColMajor);
RenderHeatmap(draw_list, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true, col_maj);
@@ -2651,10 +2539,6 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
}
if (BeginItemEx(label_id, FitterRect(range))) {
if (y_bins <= 0 || x_bins <= 0) {
EndItem();
return max_count;
}
ImDrawList& draw_list = *GetPlotDrawList();
RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj);
EndItem();
@@ -2713,8 +2597,8 @@ void PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags
//do not extend plot outside plot range
if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin;
if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin;
if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976
if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976
if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax;
if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax;
//plot a rectangle that extends up to x2 with y1 height
if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) {
// ImVec4 colAlpha = item->Color;

View File

@@ -11,7 +11,6 @@
#include <cstddef>
#include <string>
#include <string_view>
namespace llvm {
/// This is a llvm local version of __cxa_demangle. Other than the name and
@@ -29,10 +28,8 @@ enum : int {
demangle_success = 0,
};
/// Returns a non-NULL pointer to a NUL-terminated C style string
/// that should be explicitly freed, if successful. Otherwise, may return
/// nullptr if mangled_name is not a valid mangling or is nullptr.
char *itaniumDemangle(std::string_view mangled_name);
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
int *status);
enum MSDemangleFlags {
MSDF_None = 0,
@@ -49,25 +46,31 @@ enum MSDemangleFlags {
/// success, or nullptr on error.
/// If n_read is non-null and demangling was successful, it receives how many
/// bytes of the input string were consumed.
/// buf can point to a *n_buf bytes large buffer where the demangled name is
/// stored. If the buffer is too small, it is grown with realloc(). If buf is
/// nullptr, then this malloc()s memory for the result.
/// *n_buf stores the size of buf on input if buf is non-nullptr, and it
/// receives the size of the demangled string on output if n_buf is not nullptr.
/// status receives one of the demangle_ enum entries above if it's not nullptr.
/// Flags controls various details of the demangled representation.
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
int *status, MSDemangleFlags Flags = MSDF_None);
char *microsoftDemangle(const char *mangled_name, size_t *n_read, char *buf,
size_t *n_buf, int *status,
MSDemangleFlags Flags = MSDF_None);
// Demangles a Rust v0 mangled symbol.
char *rustDemangle(std::string_view MangledName);
char *rustDemangle(const char *MangledName);
// Demangles a D mangled symbol.
char *dlangDemangle(std::string_view MangledName);
char *dlangDemangle(const char *MangledName);
/// Attempt to demangle a string using different demangling schemes.
/// The function uses heuristics to determine which demangling scheme to use.
/// \param MangledName - reference to string to demangle.
/// \returns - the demangled string, or a copy of the input string if no
/// demangling occurred.
std::string demangle(std::string_view MangledName);
std::string demangle(const std::string &MangledName);
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
bool nonMicrosoftDemangle(const char *MangledName, std::string &Result);
/// "Partial" demangler. This supports demangling a string into an AST
/// (typically an intermediate stage in itaniumDemangle) and querying certain
@@ -84,7 +87,7 @@ struct ItaniumPartialDemangler {
bool partialDemangle(const char *MangledName);
/// Just print the entire mangled name into Buf. Buf and N behave like the
/// second and third parameters to __cxa_demangle.
/// second and third parameters to itaniumDemangle.
char *finishDemangle(char *Buf, size_t *N) const;
/// Get the base name of a function. This doesn't include trailing template

View File

@@ -13,11 +13,11 @@
//
//===----------------------------------------------------------------------===//
#ifndef DEMANGLE_ITANIUMDEMANGLE_H
#define DEMANGLE_ITANIUMDEMANGLE_H
#ifndef LLVM_DEMANGLE_ITANIUMDEMANGLE_H
#define LLVM_DEMANGLE_ITANIUMDEMANGLE_H
#include "DemangleConfig.h"
#include "StringViewExtras.h"
#include "StringView.h"
#include "Utility.h"
#include <algorithm>
#include <cassert>
@@ -26,9 +26,6 @@
#include <cstdlib>
#include <cstring>
#include <limits>
#include <new>
#include <string_view>
#include <type_traits>
#include <utility>
DEMANGLE_NAMESPACE_BEGIN
@@ -288,7 +285,7 @@ public:
// implementation.
virtual void printRight(OutputBuffer &) const {}
virtual std::string_view getBaseName() const { return {}; }
virtual StringView getBaseName() const { return StringView(); }
// Silence compiler warnings, this dtor will never be called.
virtual ~Node() = default;
@@ -347,10 +344,10 @@ struct NodeArrayNode : Node {
class DotSuffix final : public Node {
const Node *Prefix;
const std::string_view Suffix;
const StringView Suffix;
public:
DotSuffix(const Node *Prefix_, std::string_view Suffix_)
DotSuffix(const Node *Prefix_, StringView Suffix_)
: Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
@@ -365,15 +362,15 @@ public:
class VendorExtQualType final : public Node {
const Node *Ty;
std::string_view Ext;
StringView Ext;
const Node *TA;
public:
VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)
VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
: Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
const Node *getTy() const { return Ty; }
std::string_view getExt() const { return Ext; }
StringView getExt() const { return Ext; }
const Node *getTA() const { return TA; }
template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
@@ -464,10 +461,10 @@ public:
class PostfixQualifiedType final : public Node {
const Node *Ty;
const std::string_view Postfix;
const StringView Postfix;
public:
PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
: Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
@@ -479,15 +476,15 @@ public:
};
class NameType final : public Node {
const std::string_view Name;
const StringView Name;
public:
NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}
NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
template<typename Fn> void match(Fn F) const { F(Name); }
std::string_view getName() const { return Name; }
std::string_view getBaseName() const override { return Name; }
StringView getName() const { return Name; }
StringView getBaseName() const override { return Name; }
void printLeft(OutputBuffer &OB) const override { OB += Name; }
};
@@ -513,10 +510,10 @@ public:
};
class ElaboratedTypeSpefType : public Node {
std::string_view Kind;
StringView Kind;
Node *Child;
public:
ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
: Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
template<typename Fn> void match(Fn F) const { F(Kind, Child); }
@@ -530,17 +527,15 @@ public:
struct AbiTagAttr : Node {
Node *Base;
std::string_view Tag;
StringView Tag;
AbiTagAttr(Node *Base_, std::string_view Tag_)
: Node(KAbiTagAttr, Base_->RHSComponentCache, Base_->ArrayCache,
Base_->FunctionCache),
AbiTagAttr(Node* Base_, StringView Tag_)
: Node(KAbiTagAttr, Base_->RHSComponentCache,
Base_->ArrayCache, Base_->FunctionCache),
Base(Base_), Tag(Tag_) {}
template<typename Fn> void match(Fn F) const { F(Base, Tag); }
std::string_view getBaseName() const override { return Base->getBaseName(); }
void printLeft(OutputBuffer &OB) const override {
Base->printLeft(OB);
OB += "[abi:";
@@ -566,12 +561,12 @@ public:
class ObjCProtoName : public Node {
const Node *Ty;
std::string_view Protocol;
StringView Protocol;
friend class PointerType;
public:
ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
ObjCProtoName(const Node *Ty_, StringView Protocol_)
: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
@@ -948,11 +943,11 @@ public:
};
class SpecialName final : public Node {
const std::string_view Special;
const StringView Special;
const Node *Child;
public:
SpecialName(std::string_view Special_, const Node *Child_)
SpecialName(StringView Special_, const Node *Child_)
: Node(KSpecialName), Special(Special_), Child(Child_) {}
template<typename Fn> void match(Fn F) const { F(Special, Child); }
@@ -991,7 +986,7 @@ struct NestedName : Node {
template<typename Fn> void match(Fn F) const { F(Qual, Name); }
std::string_view getBaseName() const override { return Name->getBaseName(); }
StringView getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override {
Qual->print(OB);
@@ -1031,7 +1026,7 @@ struct ModuleEntity : Node {
template <typename Fn> void match(Fn F) const { F(Module, Name); }
std::string_view getBaseName() const override { return Name->getBaseName(); }
StringView getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override {
Name->print(OB);
@@ -1067,7 +1062,7 @@ public:
template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
std::string_view getBaseName() const override { return Name->getBaseName(); }
StringView getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override {
Qualifier->print(OB);
@@ -1489,7 +1484,7 @@ struct NameWithTemplateArgs : Node {
template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
std::string_view getBaseName() const override { return Name->getBaseName(); }
StringView getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override {
Name->print(OB);
@@ -1506,7 +1501,7 @@ public:
template<typename Fn> void match(Fn F) const { F(Child); }
std::string_view getBaseName() const override { return Child->getBaseName(); }
StringView getBaseName() const override { return Child->getBaseName(); }
void printLeft(OutputBuffer &OB) const override {
OB += "::";
@@ -1542,20 +1537,20 @@ protected:
return unsigned(SSK) >= unsigned(SpecialSubKind::string);
}
std::string_view getBaseName() const override {
StringView getBaseName() const override {
switch (SSK) {
case SpecialSubKind::allocator:
return {"allocator"};
return StringView("allocator");
case SpecialSubKind::basic_string:
return {"basic_string"};
return StringView("basic_string");
case SpecialSubKind::string:
return {"basic_string"};
return StringView("basic_string");
case SpecialSubKind::istream:
return {"basic_istream"};
return StringView("basic_istream");
case SpecialSubKind::ostream:
return {"basic_ostream"};
return StringView("basic_ostream");
case SpecialSubKind::iostream:
return {"basic_iostream"};
return StringView("basic_iostream");
}
DEMANGLE_UNREACHABLE;
}
@@ -1579,12 +1574,12 @@ public:
template<typename Fn> void match(Fn F) const { F(SSK); }
std::string_view getBaseName() const override {
std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
StringView getBaseName() const override {
auto SV = ExpandedSpecialSubstitution::getBaseName ();
if (isInstantiation()) {
// The instantiations are typedefs that drop the "basic_" prefix.
assert(llvm::itanium_demangle::starts_with(SV, "basic_"));
SV.remove_prefix(sizeof("basic_") - 1);
assert(SV.startsWith("basic_"));
SV = SV.dropFront(sizeof("basic_") - 1);
}
return SV;
}
@@ -1632,11 +1627,10 @@ public:
};
class UnnamedTypeName : public Node {
const std::string_view Count;
const StringView Count;
public:
UnnamedTypeName(std::string_view Count_)
: Node(KUnnamedTypeName), Count(Count_) {}
UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
template<typename Fn> void match(Fn F) const { F(Count); }
@@ -1650,11 +1644,11 @@ public:
class ClosureTypeName : public Node {
NodeArray TemplateParams;
NodeArray Params;
std::string_view Count;
StringView Count;
public:
ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
std::string_view Count_)
StringView Count_)
: Node(KClosureTypeName), TemplateParams(TemplateParams_),
Params(Params_), Count(Count_) {}
@@ -1701,12 +1695,12 @@ public:
class BinaryExpr : public Node {
const Node *LHS;
const std::string_view InfixOperator;
const StringView InfixOperator;
const Node *RHS;
public:
BinaryExpr(const Node *LHS_, std::string_view InfixOperator_,
const Node *RHS_, Prec Prec_)
BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
Prec Prec_)
: Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
RHS(RHS_) {}
@@ -1755,10 +1749,10 @@ public:
class PostfixExpr : public Node {
const Node *Child;
const std::string_view Operator;
const StringView Operator;
public:
PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)
PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
: Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
template <typename Fn> void match(Fn F) const {
@@ -1796,12 +1790,11 @@ public:
class MemberExpr : public Node {
const Node *LHS;
const std::string_view Kind;
const StringView Kind;
const Node *RHS;
public:
MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_,
Prec Prec_)
MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
: Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
template <typename Fn> void match(Fn F) const {
@@ -1818,14 +1811,13 @@ public:
class SubobjectExpr : public Node {
const Node *Type;
const Node *SubExpr;
std::string_view Offset;
StringView Offset;
NodeArray UnionSelectors;
bool OnePastTheEnd;
public:
SubobjectExpr(const Node *Type_, const Node *SubExpr_,
std::string_view Offset_, NodeArray UnionSelectors_,
bool OnePastTheEnd_)
SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
NodeArray UnionSelectors_, bool OnePastTheEnd_)
: Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
@@ -1842,7 +1834,7 @@ public:
OB += "0";
} else if (Offset[0] == 'n') {
OB += "-";
OB += std::string_view(Offset.data() + 1, Offset.size() - 1);
OB += Offset.dropFront();
} else {
OB += Offset;
}
@@ -1851,12 +1843,12 @@ public:
};
class EnclosingExpr : public Node {
const std::string_view Prefix;
const StringView Prefix;
const Node *Infix;
const std::string_view Postfix;
const StringView Postfix;
public:
EnclosingExpr(std::string_view Prefix_, const Node *Infix_,
EnclosingExpr(StringView Prefix_, const Node *Infix_,
Prec Prec_ = Prec::Primary)
: Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
@@ -1875,13 +1867,12 @@ public:
class CastExpr : public Node {
// cast_kind<to>(from)
const std::string_view CastKind;
const StringView CastKind;
const Node *To;
const Node *From;
public:
CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_,
Prec Prec_)
CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
: Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
template <typename Fn> void match(Fn F) const {
@@ -2004,11 +1995,11 @@ public:
};
class PrefixExpr : public Node {
std::string_view Prefix;
StringView Prefix;
Node *Child;
public:
PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)
PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
: Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
template <typename Fn> void match(Fn F) const {
@@ -2022,11 +2013,10 @@ public:
};
class FunctionParam : public Node {
std::string_view Number;
StringView Number;
public:
FunctionParam(std::string_view Number_)
: Node(KFunctionParam), Number(Number_) {}
FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
template<typename Fn> void match(Fn F) const { F(Number); }
@@ -2061,11 +2051,11 @@ public:
class PointerToMemberConversionExpr : public Node {
const Node *Type;
const Node *SubExpr;
std::string_view Offset;
StringView Offset;
public:
PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
std::string_view Offset_, Prec Prec_)
StringView Offset_, Prec Prec_)
: Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
SubExpr(SubExpr_), Offset(Offset_) {}
@@ -2150,11 +2140,11 @@ public:
class FoldExpr : public Node {
const Node *Pack, *Init;
std::string_view OperatorName;
StringView OperatorName;
bool IsLeftFold;
public:
FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,
FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
const Node *Init_)
: Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
IsLeftFold(IsLeftFold_) {}
@@ -2218,7 +2208,7 @@ public:
template<typename Fn> void match(Fn F) const { F(Value); }
void printLeft(OutputBuffer &OB) const override {
OB += Value ? std::string_view("true") : std::string_view("false");
OB += Value ? StringView("true") : StringView("false");
}
};
@@ -2256,10 +2246,10 @@ public:
class EnumLiteral : public Node {
// ty(integer)
const Node *Ty;
std::string_view Integer;
StringView Integer;
public:
EnumLiteral(const Node *Ty_, std::string_view Integer_)
EnumLiteral(const Node *Ty_, StringView Integer_)
: Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
@@ -2270,18 +2260,18 @@ public:
OB.printClose();
if (Integer[0] == 'n')
OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);
OB << "-" << Integer.dropFront(1);
else
OB << Integer;
}
};
class IntegerLiteral : public Node {
std::string_view Type;
std::string_view Value;
StringView Type;
StringView Value;
public:
IntegerLiteral(std::string_view Type_, std::string_view Value_)
IntegerLiteral(StringView Type_, StringView Value_)
: Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
template<typename Fn> void match(Fn F) const { F(Type, Value); }
@@ -2293,9 +2283,10 @@ public:
OB.printClose();
}
if (Value[0] == 'n')
OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);
else
if (Value[0] == 'n') {
OB += '-';
OB += Value.dropFront(1);
} else
OB += Value;
if (Type.size() <= 3)
@@ -2318,26 +2309,29 @@ constexpr Node::Kind getFloatLiteralKind(long double *) {
}
template <class Float> class FloatLiteralImpl : public Node {
const std::string_view Contents;
const StringView Contents;
static constexpr Kind KindForClass =
float_literal_impl::getFloatLiteralKind((Float *)nullptr);
public:
FloatLiteralImpl(std::string_view Contents_)
FloatLiteralImpl(StringView Contents_)
: Node(KindForClass), Contents(Contents_) {}
template<typename Fn> void match(Fn F) const { F(Contents); }
void printLeft(OutputBuffer &OB) const override {
const char *first = Contents.begin();
const char *last = Contents.end() + 1;
const size_t N = FloatData<Float>::mangled_size;
if (Contents.size() >= N) {
if (static_cast<std::size_t>(last - first) > N) {
last = first + N;
union {
Float value;
char buf[sizeof(Float)];
};
const char *t = Contents.data();
const char *last = t + N;
const char *t = first;
char *e = buf;
for (; t != last; ++t, ++e) {
unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
@@ -2352,7 +2346,7 @@ public:
#endif
char num[FloatData<Float>::max_demangled_size] = {0};
int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
OB += std::string_view(num, n);
OB += StringView(num, num + n);
}
}
};
@@ -2479,9 +2473,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
return res;
}
bool consumeIf(std::string_view S) {
if (llvm::itanium_demangle::starts_with(
std::string_view(First, Last - First), S)) {
bool consumeIf(StringView S) {
if (StringView(First, Last).startsWith(S)) {
First += S.size();
return true;
}
@@ -2506,10 +2499,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
size_t numLeft() const { return static_cast<size_t>(Last - First); }
std::string_view parseNumber(bool AllowNegative = false);
StringView parseNumber(bool AllowNegative = false);
Qualifiers parseCVQualifiers();
bool parsePositiveInteger(size_t *Out);
std::string_view parseBareSourceName();
StringView parseBareSourceName();
bool parseSeqId(size_t *Out);
Node *parseSubstitution();
@@ -2520,9 +2513,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
/// Parse the <expr> production.
Node *parseExpr();
Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
Node *parseIntegerLiteral(std::string_view Lit);
Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Node *parseIntegerLiteral(StringView Lit);
Node *parseExprPrimary();
template <class Float> Node *parseFloatingLiteral();
Node *parseFunctionParam();
@@ -2630,18 +2623,17 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
public:
std::string_view getSymbol() const {
std::string_view Res = Name;
StringView getSymbol() const {
StringView Res = Name;
if (Kind < Unnameable) {
assert(llvm::itanium_demangle::starts_with(Res, "operator") &&
assert(Res.startsWith("operator") &&
"operator name does not start with 'operator'");
Res.remove_prefix(sizeof("operator") - 1);
if (llvm::itanium_demangle::starts_with(Res, ' '))
Res.remove_prefix(1);
Res = Res.dropFront(sizeof("operator") - 1);
Res.consumeFront(' ');
}
return Res;
}
std::string_view getName() const { return Name; }
StringView getName() const { return Name; }
OIKind getKind() const { return Kind; }
bool getFlag() const { return Flag; }
Node::Prec getPrecedence() const { return Prec; }
@@ -2861,7 +2853,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
TemplateParams.clear();
if (consumeIf("Ut")) {
std::string_view Count = parseNumber();
StringView Count = parseNumber();
if (!consumeIf('_'))
return nullptr;
return make<UnnamedTypeName>(Count);
@@ -2873,7 +2865,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
size_t ParamsBegin = Names.size();
while (look() == 'T' &&
std::string_view("yptn").find(look(1)) != std::string_view::npos) {
StringView("yptn").find(look(1)) != StringView::npos) {
Node *T = parseTemplateParamDecl();
if (!T)
return nullptr;
@@ -2916,7 +2908,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
}
NodeArray Params = popTrailingNodeArray(ParamsBegin);
std::string_view Count = parseNumber();
StringView Count = parseNumber();
if (!consumeIf('_'))
return nullptr;
return make<ClosureTypeName>(TempParams, Params, Count);
@@ -2938,9 +2930,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
return nullptr;
if (numLeft() < Length || Length == 0)
return nullptr;
std::string_view Name(First, Length);
StringView Name(First, First + Length);
First += Length;
if (llvm::itanium_demangle::starts_with(Name, "_GLOBAL__N"))
if (Name.startsWith("_GLOBAL__N"))
return make<NameType>("(anonymous namespace)");
return make<NameType>(Name);
}
@@ -3039,21 +3031,14 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
if (numLeft() < 2)
return nullptr;
// We can't use lower_bound as that can link to symbols in the C++ library,
// and this must remain independant of that.
size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.
while (upper != lower) {
size_t middle = (upper + lower) / 2;
if (Ops[middle] < First)
lower = middle + 1;
else
upper = middle;
}
if (Ops[lower] != First)
auto Op = std::lower_bound(
&Ops[0], &Ops[NumOps], First,
[](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
if (Op == &Ops[NumOps] || *Op != First)
return nullptr;
First += 2;
return &Ops[lower];
return Op;
}
// <operator-name> ::= See parseOperatorEncoding()
@@ -3454,7 +3439,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
while (consumeIf('B')) {
std::string_view SN = parseBareSourceName();
StringView SN = parseBareSourceName();
if (SN.empty())
return nullptr;
N = make<AbiTagAttr>(N, SN);
@@ -3466,16 +3451,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
// <number> ::= [n] <non-negative decimal integer>
template <typename Alloc, typename Derived>
std::string_view
StringView
AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
const char *Tmp = First;
if (AllowNegative)
consumeIf('n');
if (numLeft() == 0 || !std::isdigit(*First))
return std::string_view();
return StringView();
while (numLeft() != 0 && std::isdigit(*First))
++First;
return std::string_view(Tmp, First - Tmp);
return StringView(Tmp, First);
}
// <positive length number> ::= [0-9]*
@@ -3492,11 +3477,11 @@ bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
}
template <typename Alloc, typename Derived>
std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
size_t Int = 0;
if (parsePositiveInteger(&Int) || numLeft() < Int)
return {};
std::string_view R(First, Int);
return StringView();
StringView R(First, First + Int);
First += Int;
return R;
}
@@ -3680,7 +3665,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
// ::= Te <name> # dependent elaborated type specifier using 'enum'
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
std::string_view ElabSpef;
StringView ElabSpef;
if (consumeIf("Ts"))
ElabSpef = "struct";
else if (consumeIf("Tu"))
@@ -3704,18 +3689,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
if (consumeIf('U')) {
std::string_view Qual = parseBareSourceName();
StringView Qual = parseBareSourceName();
if (Qual.empty())
return nullptr;
// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
if (llvm::itanium_demangle::starts_with(Qual, "objcproto")) {
constexpr size_t Len = sizeof("objcproto") - 1;
std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
std::string_view Proto;
if (Qual.startsWith("objcproto")) {
StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
StringView Proto;
{
ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),
SaveLast(Last, &*ProtoSourceName.rbegin() + 1);
ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
SaveLast(Last, ProtoSourceName.end());
Proto = parseBareSourceName();
}
if (Proto.empty())
@@ -3883,7 +3867,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
// <builtin-type> ::= u <source-name> # vendor extended type
case 'u': {
++First;
std::string_view Res = parseBareSourceName();
StringView Res = parseBareSourceName();
if (Res.empty())
return nullptr;
// Typically, <builtin-type>s are not considered substitution candidates,
@@ -4131,9 +4115,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
}
template <typename Derived, typename Alloc>
Node *
AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,
Node::Prec Prec) {
Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
Node::Prec Prec) {
Node *E = getDerived().parseExpr();
if (E == nullptr)
return nullptr;
@@ -4141,9 +4124,8 @@ AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,
}
template <typename Derived, typename Alloc>
Node *
AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,
Node::Prec Prec) {
Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
Node::Prec Prec) {
Node *LHS = getDerived().parseExpr();
if (LHS == nullptr)
return nullptr;
@@ -4154,9 +4136,9 @@ AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,
}
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(
std::string_view Lit) {
std::string_view Tmp = parseNumber(true);
Node *
AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
StringView Tmp = parseNumber(true);
if (!Tmp.empty() && consumeIf('E'))
return make<IntegerLiteral>(Lit, Tmp);
return nullptr;
@@ -4186,7 +4168,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
return make<NameType>("this");
if (consumeIf("fp")) {
parseCVQualifiers();
std::string_view Num = parseNumber();
StringView Num = parseNumber();
if (!consumeIf('_'))
return nullptr;
return make<FunctionParam>(Num);
@@ -4197,7 +4179,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
if (!consumeIf('p'))
return nullptr;
parseCVQualifiers();
std::string_view Num = parseNumber();
StringView Num = parseNumber();
if (!consumeIf('_'))
return nullptr;
return make<FunctionParam>(Num);
@@ -4351,7 +4333,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Node *T = getDerived().parseType();
if (T == nullptr)
return nullptr;
std::string_view N = parseNumber(/*AllowNegative=*/true);
StringView N = parseNumber(/*AllowNegative=*/true);
if (N.empty())
return nullptr;
if (!consumeIf('E'))
@@ -4474,7 +4456,7 @@ AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
Node *Expr = getDerived().parseExpr();
if (!Expr)
return nullptr;
std::string_view Offset = getDerived().parseNumber(true);
StringView Offset = getDerived().parseNumber(true);
if (!consumeIf('E'))
return nullptr;
return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
@@ -4492,7 +4474,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
Node *Expr = getDerived().parseExpr();
if (!Expr)
return nullptr;
std::string_view Offset = getDerived().parseNumber(true);
StringView Offset = getDerived().parseNumber(true);
size_t SelectorsBegin = Names.size();
while (consumeIf('_')) {
Node *Selector = make<NameType>(parseNumber());
@@ -5129,7 +5111,7 @@ template <>
struct FloatData<long double>
{
#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
defined(__wasm__) || defined(__riscv) || defined(__loongarch__)
defined(__wasm__) || defined(__riscv)
static const size_t mangled_size = 32;
#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
static const size_t mangled_size = 16;
@@ -5151,7 +5133,7 @@ Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
const size_t N = FloatData<Float>::mangled_size;
if (numLeft() <= N)
return nullptr;
std::string_view Data(First, N);
StringView Data(First, First + N);
for (char C : Data)
if (!std::isxdigit(C))
return nullptr;
@@ -5471,8 +5453,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
if (Encoding == nullptr)
return nullptr;
if (look() == '.') {
Encoding =
make<DotSuffix>(Encoding, std::string_view(First, Last - First));
Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
First = Last;
}
if (numLeft() != 0)
@@ -5508,4 +5489,4 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
DEMANGLE_NAMESPACE_END
#endif // DEMANGLE_ITANIUMDEMANGLE_H
#endif // LLVM_DEMANGLE_ITANIUMDEMANGLE_H

View File

@@ -10,9 +10,8 @@
#define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
#include "llvm/Demangle/StringView.h"
#include <cassert>
#include <string_view>
#include <utility>
namespace llvm {
@@ -101,7 +100,7 @@ public:
if (Head->Used <= Head->Capacity)
return new (PP) T(std::forward<Args>(ConstructorArgs)...);
static_assert(Size < AllocUnit);
static_assert(Size < AllocUnit, "");
addNode(AllocUnit);
Head->Used = Size;
return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
@@ -143,9 +142,9 @@ public:
// You are supposed to call parse() first and then check if error is true. If
// it is false, call output() to write the formatted name to the given stream.
SymbolNode *parse(std::string_view &MangledName);
SymbolNode *parse(StringView &MangledName);
TagTypeNode *parseTagUniqueName(std::string_view &MangledName);
TagTypeNode *parseTagUniqueName(StringView &MangledName);
// True if an error occurred.
bool Error = false;
@@ -153,112 +152,104 @@ public:
void dumpBackReferences();
private:
SymbolNode *demangleEncodedSymbol(std::string_view &MangledName,
SymbolNode *demangleEncodedSymbol(StringView &MangledName,
QualifiedNameNode *QN);
SymbolNode *demangleDeclarator(std::string_view &MangledName);
SymbolNode *demangleMD5Name(std::string_view &MangledName);
SymbolNode *demangleTypeinfoName(std::string_view &MangledName);
SymbolNode *demangleDeclarator(StringView &MangledName);
SymbolNode *demangleMD5Name(StringView &MangledName);
SymbolNode *demangleTypeinfoName(StringView &MangledName);
VariableSymbolNode *demangleVariableEncoding(std::string_view &MangledName,
VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,
StorageClass SC);
FunctionSymbolNode *demangleFunctionEncoding(std::string_view &MangledName);
FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);
Qualifiers demanglePointerExtQualifiers(std::string_view &MangledName);
Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
// Parser functions. This is a recursive-descent parser.
TypeNode *demangleType(std::string_view &MangledName,
QualifierMangleMode QMM);
PrimitiveTypeNode *demanglePrimitiveType(std::string_view &MangledName);
CustomTypeNode *demangleCustomType(std::string_view &MangledName);
TagTypeNode *demangleClassType(std::string_view &MangledName);
PointerTypeNode *demanglePointerType(std::string_view &MangledName);
PointerTypeNode *demangleMemberPointerType(std::string_view &MangledName);
FunctionSignatureNode *demangleFunctionType(std::string_view &MangledName,
TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);
PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);
CustomTypeNode *demangleCustomType(StringView &MangledName);
TagTypeNode *demangleClassType(StringView &MangledName);
PointerTypeNode *demanglePointerType(StringView &MangledName);
PointerTypeNode *demangleMemberPointerType(StringView &MangledName);
FunctionSignatureNode *demangleFunctionType(StringView &MangledName,
bool HasThisQuals);
ArrayTypeNode *demangleArrayType(std::string_view &MangledName);
ArrayTypeNode *demangleArrayType(StringView &MangledName);
NodeArrayNode *demangleFunctionParameterList(std::string_view &MangledName,
NodeArrayNode *demangleFunctionParameterList(StringView &MangledName,
bool &IsVariadic);
NodeArrayNode *demangleTemplateParameterList(std::string_view &MangledName);
NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);
std::pair<uint64_t, bool> demangleNumber(std::string_view &MangledName);
uint64_t demangleUnsigned(std::string_view &MangledName);
int64_t demangleSigned(std::string_view &MangledName);
std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
uint64_t demangleUnsigned(StringView &MangledName);
int64_t demangleSigned(StringView &MangledName);
void memorizeString(std::string_view s);
void memorizeString(StringView s);
void memorizeIdentifier(IdentifierNode *Identifier);
/// Allocate a copy of \p Borrowed into memory that we own.
std::string_view copyString(std::string_view Borrowed);
StringView copyString(StringView Borrowed);
QualifiedNameNode *
demangleFullyQualifiedTypeName(std::string_view &MangledName);
QualifiedNameNode *
demangleFullyQualifiedSymbolName(std::string_view &MangledName);
QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);
QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);
IdentifierNode *demangleUnqualifiedTypeName(std::string_view &MangledName,
IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,
bool Memorize);
IdentifierNode *demangleUnqualifiedSymbolName(std::string_view &MangledName,
IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,
NameBackrefBehavior NBB);
QualifiedNameNode *demangleNameScopeChain(std::string_view &MangledName,
QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,
IdentifierNode *UnqualifiedName);
IdentifierNode *demangleNameScopePiece(std::string_view &MangledName);
IdentifierNode *demangleNameScopePiece(StringView &MangledName);
NamedIdentifierNode *demangleBackRefName(std::string_view &MangledName);
IdentifierNode *
demangleTemplateInstantiationName(std::string_view &MangledName,
NameBackrefBehavior NBB);
NamedIdentifierNode *demangleBackRefName(StringView &MangledName);
IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,
NameBackrefBehavior NBB);
IntrinsicFunctionKind
translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
IdentifierNode *demangleFunctionIdentifierCode(std::string_view &MangledName);
IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);
IdentifierNode *
demangleFunctionIdentifierCode(std::string_view &MangledName,
demangleFunctionIdentifierCode(StringView &MangledName,
FunctionIdentifierCodeGroup Group);
StructorIdentifierNode *
demangleStructorIdentifier(std::string_view &MangledName, bool IsDestructor);
StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,
bool IsDestructor);
ConversionOperatorIdentifierNode *
demangleConversionOperatorIdentifier(std::string_view &MangledName);
demangleConversionOperatorIdentifier(StringView &MangledName);
LiteralOperatorIdentifierNode *
demangleLiteralOperatorIdentifier(std::string_view &MangledName);
demangleLiteralOperatorIdentifier(StringView &MangledName);
SymbolNode *demangleSpecialIntrinsic(std::string_view &MangledName);
SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);
SpecialTableSymbolNode *
demangleSpecialTableSymbolNode(std::string_view &MangledName,
demangleSpecialTableSymbolNode(StringView &MangledName,
SpecialIntrinsicKind SIK);
LocalStaticGuardVariableNode *
demangleLocalStaticGuard(std::string_view &MangledName, bool IsThread);
demangleLocalStaticGuard(StringView &MangledName, bool IsThread);
VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
std::string_view &MangledName,
std::string_view VariableName);
StringView &MangledName,
StringView VariableName);
VariableSymbolNode *
demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
std::string_view &MangledName);
FunctionSymbolNode *demangleInitFiniStub(std::string_view &MangledName,
StringView &MangledName);
FunctionSymbolNode *demangleInitFiniStub(StringView &MangledName,
bool IsDestructor);
NamedIdentifierNode *demangleSimpleName(std::string_view &MangledName,
NamedIdentifierNode *demangleSimpleName(StringView &MangledName,
bool Memorize);
NamedIdentifierNode *
demangleAnonymousNamespaceName(std::string_view &MangledName);
NamedIdentifierNode *
demangleLocallyScopedNamePiece(std::string_view &MangledName);
EncodedStringLiteralNode *
demangleStringLiteral(std::string_view &MangledName);
FunctionSymbolNode *demangleVcallThunkNode(std::string_view &MangledName);
NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);
NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);
EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);
FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);
std::string_view demangleSimpleString(std::string_view &MangledName,
bool Memorize);
StringView demangleSimpleString(StringView &MangledName, bool Memorize);
FuncClass demangleFunctionClass(std::string_view &MangledName);
CallingConv demangleCallingConvention(std::string_view &MangledName);
StorageClass demangleVariableStorageClass(std::string_view &MangledName);
bool demangleThrowSpecification(std::string_view &MangledName);
wchar_t demangleWcharLiteral(std::string_view &MangledName);
uint8_t demangleCharLiteral(std::string_view &MangledName);
FuncClass demangleFunctionClass(StringView &MangledName);
CallingConv demangleCallingConvention(StringView &MangledName);
StorageClass demangleVariableStorageClass(StringView &MangledName);
bool demangleThrowSpecification(StringView &MangledName);
wchar_t demangleWcharLiteral(StringView &MangledName);
uint8_t demangleCharLiteral(StringView &MangledName);
std::pair<Qualifiers, bool> demangleQualifiers(std::string_view &MangledName);
std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName);
// Memory allocator.
ArenaAllocator Arena;

View File

@@ -13,10 +13,10 @@
#ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
#define LLVM_DEMANGLE_MICROSOFTDEMANGLENODES_H
#include "llvm/Demangle/StringView.h"
#include <array>
#include <cstdint>
#include <string>
#include <string_view>
namespace llvm {
namespace itanium_demangle {
@@ -25,6 +25,7 @@ class OutputBuffer;
}
using llvm::itanium_demangle::OutputBuffer;
using llvm::itanium_demangle::StringView;
namespace llvm {
namespace ms_demangle {
@@ -383,7 +384,7 @@ struct NamedIdentifierNode : public IdentifierNode {
void output(OutputBuffer &OB, OutputFlags Flags) const override;
std::string_view Name;
StringView Name;
};
struct IntrinsicFunctionIdentifierNode : public IdentifierNode {
@@ -402,7 +403,7 @@ struct LiteralOperatorIdentifierNode : public IdentifierNode {
void output(OutputBuffer &OB, OutputFlags Flags) const override;
std::string_view Name;
StringView Name;
};
struct LocalStaticGuardIdentifierNode : public IdentifierNode {
@@ -515,8 +516,7 @@ struct NodeArrayNode : public Node {
void output(OutputBuffer &OB, OutputFlags Flags) const override;
void output(OutputBuffer &OB, OutputFlags Flags,
std::string_view Separator) const;
void output(OutputBuffer &OB, OutputFlags Flags, StringView Separator) const;
Node **Nodes = nullptr;
size_t Count = 0;
@@ -601,7 +601,7 @@ struct EncodedStringLiteralNode : public SymbolNode {
void output(OutputBuffer &OB, OutputFlags Flags) const override;
std::string_view DecodedString;
StringView DecodedString;
bool IsTruncated = false;
CharKind Char = CharKind::Char;
};

View File

@@ -0,0 +1,122 @@
//===--- StringView.h ----------------*- mode:c++;eval:(read-only-mode) -*-===//
// Do not edit! See README.txt.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// FIXME: Use std::string_view instead when we support C++17.
// There are two copies of this file in the source tree. The one under
// libcxxabi is the original and the one under llvm is the copy. Use
// cp-to-llvm.sh to update the copy. See README.txt for more details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEMANGLE_STRINGVIEW_H
#define LLVM_DEMANGLE_STRINGVIEW_H
#include "DemangleConfig.h"
#include <cassert>
#include <cstring>
DEMANGLE_NAMESPACE_BEGIN
class StringView {
const char *First;
const char *Last;
public:
static const size_t npos = ~size_t(0);
template <size_t N>
StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
StringView(const char *First_, const char *Last_)
: First(First_), Last(Last_) {}
StringView(const char *First_, size_t Len)
: First(First_), Last(First_ + Len) {}
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
StringView() : First(nullptr), Last(nullptr) {}
StringView substr(size_t Pos, size_t Len = npos) const {
assert(Pos <= size());
if (Len > size() - Pos)
Len = size() - Pos;
return StringView(begin() + Pos, Len);
}
size_t find(char C, size_t From = 0) const {
// Avoid calling memchr with nullptr.
if (From < size()) {
// Just forward to memchr, which is faster than a hand-rolled loop.
if (const void *P = ::memchr(First + From, C, size() - From))
return size_t(static_cast<const char *>(P) - First);
}
return npos;
}
StringView dropFront(size_t N = 1) const {
if (N >= size())
N = size();
return StringView(First + N, Last);
}
StringView dropBack(size_t N = 1) const {
if (N >= size())
N = size();
return StringView(First, Last - N);
}
char front() const {
assert(!empty());
return *begin();
}
char back() const {
assert(!empty());
return *(end() - 1);
}
char popFront() {
assert(!empty());
return *First++;
}
bool consumeFront(char C) {
if (!startsWith(C))
return false;
*this = dropFront(1);
return true;
}
bool consumeFront(StringView S) {
if (!startsWith(S))
return false;
*this = dropFront(S.size());
return true;
}
bool startsWith(char C) const { return !empty() && *begin() == C; }
bool startsWith(StringView Str) const {
if (Str.size() > size())
return false;
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
}
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
const char *begin() const { return First; }
const char *end() const { return Last; }
size_t size() const { return static_cast<size_t>(Last - First); }
bool empty() const { return First == Last; }
};
inline bool operator==(const StringView &LHS, const StringView &RHS) {
return LHS.size() == RHS.size() &&
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
}
DEMANGLE_NAMESPACE_END
#endif

View File

@@ -13,19 +13,16 @@
//
//===----------------------------------------------------------------------===//
#ifndef DEMANGLE_UTILITY_H
#define DEMANGLE_UTILITY_H
#include "DemangleConfig.h"
#ifndef LLVM_DEMANGLE_UTILITY_H
#define LLVM_DEMANGLE_UTILITY_H
#include "StringView.h"
#include <array>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <limits>
#include <string_view>
DEMANGLE_NAMESPACE_BEGIN
@@ -67,22 +64,23 @@ class OutputBuffer {
if (isNeg)
*--TempPtr = '-';
return operator+=(
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
}
public:
OutputBuffer(char *StartBuf, size_t Size)
: Buffer(StartBuf), BufferCapacity(Size) {}
OutputBuffer(char *StartBuf, size_t *SizePtr)
: OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
OutputBuffer() = default;
// Non-copyable
OutputBuffer(const OutputBuffer &) = delete;
OutputBuffer &operator=(const OutputBuffer &) = delete;
operator std::string_view() const {
return std::string_view(Buffer, CurrentPosition);
operator StringView() const { return StringView(Buffer, CurrentPosition); }
void reset(char *Buffer_, size_t BufferCapacity_) {
CurrentPosition = 0;
Buffer = Buffer_;
BufferCapacity = BufferCapacity_;
}
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
@@ -105,10 +103,10 @@ public:
*this += Close;
}
OutputBuffer &operator+=(std::string_view R) {
OutputBuffer &operator+=(StringView R) {
if (size_t Size = R.size()) {
grow(Size);
std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
CurrentPosition += Size;
}
return *this;
@@ -120,18 +118,18 @@ public:
return *this;
}
OutputBuffer &prepend(std::string_view R) {
OutputBuffer &prepend(StringView R) {
size_t Size = R.size();
grow(Size);
std::memmove(Buffer + Size, Buffer, CurrentPosition);
std::memcpy(Buffer, &*R.begin(), Size);
std::memcpy(Buffer, R.begin(), Size);
CurrentPosition += Size;
return *this;
}
OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
OutputBuffer &operator<<(StringView R) { return (*this += R); }
OutputBuffer &operator<<(char C) { return (*this += C); }
@@ -200,6 +198,21 @@ public:
ScopedOverride &operator=(const ScopedOverride &) = delete;
};
inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
size_t InitSize) {
size_t BufferSize;
if (Buf == nullptr) {
Buf = static_cast<char *>(std::malloc(InitSize));
if (Buf == nullptr)
return false;
BufferSize = InitSize;
} else
BufferSize = *N;
OB.reset(Buf, BufferSize);
return true;
}
DEMANGLE_NAMESPACE_END
#endif

View File

@@ -14,17 +14,16 @@
//===----------------------------------------------------------------------===//
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/StringViewExtras.h"
#include "llvm/Demangle/StringView.h"
#include "llvm/Demangle/Utility.h"
#include <cctype>
#include <cstring>
#include <limits>
#include <string_view>
using namespace llvm;
using llvm::itanium_demangle::OutputBuffer;
using llvm::itanium_demangle::starts_with;
using llvm::itanium_demangle::StringView;
namespace {
@@ -33,7 +32,7 @@ struct Demangler {
/// Initialize the information structure we use to pass around information.
///
/// \param Mangled String to demangle.
Demangler(std::string_view Mangled);
Demangler(const char *Mangled);
/// Extract and demangle the mangled symbol and append it to the output
/// string.
@@ -53,42 +52,46 @@ private:
/// \param Demangled output buffer to write the demangled name.
/// \param Mangled mangled symbol to be demangled.
///
/// \return The remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#name_mangling .
/// \see https://dlang.org/spec/abi.html#MangledName .
void parseMangle(OutputBuffer *Demangled, std::string_view &Mangled);
const char *parseMangle(OutputBuffer *Demangled, const char *Mangled);
/// Extract the number from a given string.
///
/// \param Mangled string to extract the number.
/// \param Ret assigned result value.
///
/// \note Ret larger than UINT_MAX is considered a failure.
/// \return The remaining string on success or nullptr on failure.
///
/// \note A result larger than UINT_MAX is considered a failure.
///
/// \see https://dlang.org/spec/abi.html#Number .
void decodeNumber(std::string_view &Mangled, unsigned long &Ret);
const char *decodeNumber(const char *Mangled, unsigned long &Ret);
/// Extract the back reference position from a given string.
///
/// \param Mangled string to extract the back reference position.
/// \param Ret assigned result value.
///
/// \return true on success, false on error.
/// \return the remaining string on success or nullptr on failure.
///
/// \note Ret is always >= 0 on success, and unspecified on failure
///
/// \see https://dlang.org/spec/abi.html#back_ref .
/// \see https://dlang.org/spec/abi.html#NumberBackRef .
bool decodeBackrefPos(std::string_view &Mangled, long &Ret);
const char *decodeBackrefPos(const char *Mangled, long &Ret);
/// Extract the symbol pointed by the back reference form a given string.
///
/// \param Mangled string to extract the back reference position.
/// \param Ret assigned result value.
///
/// \return true on success, false on error.
/// \return the remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#back_ref .
bool decodeBackref(std::string_view &Mangled, std::string_view &Ret);
const char *decodeBackref(const char *Mangled, const char *&Ret);
/// Extract and demangle backreferenced symbol from a given mangled symbol
/// and append it to the output string.
@@ -96,18 +99,22 @@ private:
/// \param Demangled output buffer to write the demangled name.
/// \param Mangled mangled symbol to be demangled.
///
/// \return the remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#back_ref .
/// \see https://dlang.org/spec/abi.html#IdentifierBackRef .
void parseSymbolBackref(OutputBuffer *Demangled, std::string_view &Mangled);
const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled);
/// Extract and demangle backreferenced type from a given mangled symbol
/// and append it to the output string.
///
/// \param Mangled mangled symbol to be demangled.
///
/// \return the remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#back_ref .
/// \see https://dlang.org/spec/abi.html#TypeBackRef .
void parseTypeBackref(std::string_view &Mangled);
const char *parseTypeBackref(const char *Mangled);
/// Check whether it is the beginning of a symbol name.
///
@@ -116,7 +123,7 @@ private:
/// \return true on success, false otherwise.
///
/// \see https://dlang.org/spec/abi.html#SymbolName .
bool isSymbolName(std::string_view Mangled);
bool isSymbolName(const char *Mangled);
/// Extract and demangle an identifier from a given mangled symbol append it
/// to the output string.
@@ -124,8 +131,10 @@ private:
/// \param Demangled Output buffer to write the demangled name.
/// \param Mangled Mangled symbol to be demangled.
///
/// \return The remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#SymbolName .
void parseIdentifier(OutputBuffer *Demangled, std::string_view &Mangled);
const char *parseIdentifier(OutputBuffer *Demangled, const char *Mangled);
/// Extract and demangle the plain identifier from a given mangled symbol and
/// prepend/append it to the output string, with a special treatment for some
@@ -135,9 +144,11 @@ private:
/// \param Mangled Mangled symbol to be demangled.
/// \param Len Length of the mangled symbol name.
///
/// \return The remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#LName .
void parseLName(OutputBuffer *Demangled, std::string_view &Mangled,
unsigned long Len);
const char *parseLName(OutputBuffer *Demangled, const char *Mangled,
unsigned long Len);
/// Extract and demangle the qualified symbol from a given mangled symbol
/// append it to the output string.
@@ -145,38 +156,33 @@ private:
/// \param Demangled Output buffer to write the demangled name.
/// \param Mangled Mangled symbol to be demangled.
///
/// \return The remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#QualifiedName .
void parseQualified(OutputBuffer *Demangled, std::string_view &Mangled);
const char *parseQualified(OutputBuffer *Demangled, const char *Mangled);
/// Extract and demangle a type from a given mangled symbol append it to
/// the output string.
///
/// \param Mangled mangled symbol to be demangled.
///
/// \return true on success, false on error.
/// \return the remaining string on success or nullptr on failure.
///
/// \see https://dlang.org/spec/abi.html#Type .
bool parseType(std::string_view &Mangled);
const char *parseType(const char *Mangled);
/// An immutable view of the string we are demangling.
const std::string_view Str;
/// The string we are demangling.
const char *Str;
/// The index of the last back reference.
int LastBackref;
};
} // namespace
void Demangler::decodeNumber(std::string_view &Mangled, unsigned long &Ret) {
// Clear Mangled if trying to extract something that isn't a digit.
if (Mangled.empty()) {
Mangled = {};
return;
}
if (!std::isdigit(Mangled.front())) {
Mangled = {};
return;
}
const char *Demangler::decodeNumber(const char *Mangled, unsigned long &Ret) {
// Return nullptr if trying to extract something that isn't a digit.
if (Mangled == nullptr || !std::isdigit(*Mangled))
return nullptr;
unsigned long Val = 0;
@@ -184,29 +190,25 @@ void Demangler::decodeNumber(std::string_view &Mangled, unsigned long &Ret) {
unsigned long Digit = Mangled[0] - '0';
// Check for overflow.
if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10) {
Mangled = {};
return;
}
if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10)
return nullptr;
Val = Val * 10 + Digit;
Mangled.remove_prefix(1);
} while (!Mangled.empty() && std::isdigit(Mangled.front()));
++Mangled;
} while (std::isdigit(*Mangled));
if (Mangled.empty()) {
Mangled = {};
return;
}
if (*Mangled == '\0')
return nullptr;
Ret = Val;
return Mangled;
}
bool Demangler::decodeBackrefPos(std::string_view &Mangled, long &Ret) {
const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) {
// Return nullptr if trying to extract something that isn't a digit
if (Mangled.empty()) {
Mangled = {};
return false;
}
if (Mangled == nullptr || !std::isalpha(*Mangled))
return nullptr;
// Any identifier or non-basic type that has been emitted to the mangled
// symbol before will not be emitted again, but is referenced by a special
// sequence encoding the relative position of the original occurrence in the
@@ -219,7 +221,7 @@ bool Demangler::decodeBackrefPos(std::string_view &Mangled, long &Ret) {
// ^
unsigned long Val = 0;
while (!Mangled.empty() && std::isalpha(Mangled.front())) {
while (std::isalpha(*Mangled)) {
// Check for overflow
if (Val > (std::numeric_limits<unsigned long>::max() - 25) / 26)
break;
@@ -231,133 +233,116 @@ bool Demangler::decodeBackrefPos(std::string_view &Mangled, long &Ret) {
if ((long)Val <= 0)
break;
Ret = Val;
Mangled.remove_prefix(1);
return true;
return Mangled + 1;
}
Val += Mangled[0] - 'A';
Mangled.remove_prefix(1);
++Mangled;
}
Mangled = {};
return false;
return nullptr;
}
bool Demangler::decodeBackref(std::string_view &Mangled,
std::string_view &Ret) {
assert(!Mangled.empty() && Mangled.front() == 'Q' &&
"Invalid back reference!");
Ret = {};
const char *Demangler::decodeBackref(const char *Mangled, const char *&Ret) {
assert(Mangled != nullptr && *Mangled == 'Q' && "Invalid back reference!");
Ret = nullptr;
// Position of 'Q'
const char *Qpos = Mangled.data();
const char *Qpos = Mangled;
long RefPos;
Mangled.remove_prefix(1);
++Mangled;
if (!decodeBackrefPos(Mangled, RefPos)) {
Mangled = {};
return false;
}
Mangled = decodeBackrefPos(Mangled, RefPos);
if (Mangled == nullptr)
return nullptr;
if (RefPos > Qpos - Str.data()) {
Mangled = {};
return false;
}
if (RefPos > Qpos - Str)
return nullptr;
// Set the position of the back reference.
Ret = Qpos - RefPos;
return true;
return Mangled;
}
void Demangler::parseSymbolBackref(OutputBuffer *Demangled,
std::string_view &Mangled) {
const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled,
const char *Mangled) {
// An identifier back reference always points to a digit 0 to 9.
// IdentifierBackRef:
// Q NumberBackRef
// ^
const char *Backref;
unsigned long Len;
// Get position of the back reference
std::string_view Backref;
if (!decodeBackref(Mangled, Backref)) {
Mangled = {};
return;
}
Mangled = decodeBackref(Mangled, Backref);
// Must point to a simple identifier
decodeNumber(Backref, Len);
if (Backref.empty() || Backref.length() < Len) {
Mangled = {};
return;
}
Backref = decodeNumber(Backref, Len);
if (Backref == nullptr || strlen(Backref) < Len)
return nullptr;
parseLName(Demangled, Backref, Len);
if (Backref.empty())
Mangled = {};
Backref = parseLName(Demangled, Backref, Len);
if (Backref == nullptr)
return nullptr;
return Mangled;
}
void Demangler::parseTypeBackref(std::string_view &Mangled) {
const char *Demangler::parseTypeBackref(const char *Mangled) {
// A type back reference always points to a letter.
// TypeBackRef:
// Q NumberBackRef
// ^
const char *Backref;
// If we appear to be moving backwards through the mangle string, then
// bail as this may be a recursive back reference.
if (Mangled.data() - Str.data() >= LastBackref) {
Mangled = {};
return;
}
if (Mangled - Str >= LastBackref)
return nullptr;
int SaveRefPos = LastBackref;
LastBackref = Mangled.data() - Str.data();
LastBackref = Mangled - Str;
// Get position of the back reference.
std::string_view Backref;
if (!decodeBackref(Mangled, Backref)) {
Mangled = {};
return;
}
Mangled = decodeBackref(Mangled, Backref);
// Can't decode back reference.
if (Backref.empty()) {
Mangled = {};
return;
}
if (Backref == nullptr)
return nullptr;
// TODO: Add support for function type back references.
if (!parseType(Backref))
Mangled = {};
Backref = parseType(Backref);
LastBackref = SaveRefPos;
if (Backref.empty())
Mangled = {};
if (Backref == nullptr)
return nullptr;
return Mangled;
}
bool Demangler::isSymbolName(std::string_view Mangled) {
bool Demangler::isSymbolName(const char *Mangled) {
long Ret;
const char *Qref = Mangled.data();
const char *Qref = Mangled;
if (std::isdigit(Mangled.front()))
if (std::isdigit(*Mangled))
return true;
// TODO: Handle template instances.
if (Mangled.front() != 'Q')
if (*Mangled != 'Q')
return false;
Mangled.remove_prefix(1);
bool Valid = decodeBackrefPos(Mangled, Ret);
if (!Valid || Ret > Qref - Str.data())
Mangled = decodeBackrefPos(Mangled + 1, Ret);
if (Mangled == nullptr || Ret > Qref - Str)
return false;
return std::isdigit(Qref[-Ret]);
}
void Demangler::parseMangle(OutputBuffer *Demangled,
std::string_view &Mangled) {
const char *Demangler::parseMangle(OutputBuffer *Demangled,
const char *Mangled) {
// A D mangled symbol is comprised of both scope and type information.
// MangleName:
// _D QualifiedName Type
@@ -367,24 +352,24 @@ void Demangler::parseMangle(OutputBuffer *Demangled,
// above location.
// Note that type is never a function type, but only the return type of
// a function or the type of a variable.
Mangled.remove_prefix(2);
Mangled += 2;
parseQualified(Demangled, Mangled);
Mangled = parseQualified(Demangled, Mangled);
if (Mangled.empty()) {
Mangled = {};
return;
if (Mangled != nullptr) {
// Artificial symbols end with 'Z' and have no type.
if (*Mangled == 'Z')
++Mangled;
else {
Mangled = parseType(Mangled);
}
}
// Artificial symbols end with 'Z' and have no type.
if (Mangled.front() == 'Z') {
Mangled.remove_prefix(1);
} else if (!parseType(Mangled))
Mangled = {};
return Mangled;
}
void Demangler::parseQualified(OutputBuffer *Demangled,
std::string_view &Mangled) {
const char *Demangler::parseQualified(OutputBuffer *Demangled,
const char *Mangled) {
// Qualified names are identifiers separated by their encoded length.
// Nested functions also encode their argument types without specifying
// what they return.
@@ -403,10 +388,10 @@ void Demangler::parseQualified(OutputBuffer *Demangled,
size_t NotFirst = false;
do {
// Skip over anonymous symbols.
if (!Mangled.empty() && Mangled.front() == '0') {
if (*Mangled == '0') {
do
Mangled.remove_prefix(1);
while (!Mangled.empty() && Mangled.front() == '0');
++Mangled;
while (*Mangled == '0');
continue;
}
@@ -415,63 +400,62 @@ void Demangler::parseQualified(OutputBuffer *Demangled,
*Demangled << '.';
NotFirst = true;
parseIdentifier(Demangled, Mangled);
} while (!Mangled.empty() && isSymbolName(Mangled));
Mangled = parseIdentifier(Demangled, Mangled);
} while (Mangled && isSymbolName(Mangled));
return Mangled;
}
void Demangler::parseIdentifier(OutputBuffer *Demangled,
std::string_view &Mangled) {
if (Mangled.empty()) {
Mangled = {};
return;
}
const char *Demangler::parseIdentifier(OutputBuffer *Demangled,
const char *Mangled) {
unsigned long Len;
if (Mangled.front() == 'Q')
if (Mangled == nullptr || *Mangled == '\0')
return nullptr;
if (*Mangled == 'Q')
return parseSymbolBackref(Demangled, Mangled);
// TODO: Parse lengthless template instances.
unsigned long Len;
decodeNumber(Mangled, Len);
const char *Endptr = decodeNumber(Mangled, Len);
if (Mangled.empty()) {
Mangled = {};
return;
}
if (!Len || Mangled.length() < Len) {
Mangled = {};
return;
}
if (Endptr == nullptr || Len == 0)
return nullptr;
if (strlen(Endptr) < Len)
return nullptr;
Mangled = Endptr;
// TODO: Parse template instances with a length prefix.
// There can be multiple different declarations in the same function that
// have the same mangled name. To make the mangled names unique, a fake
// parent in the form `__Sddd' is added to the symbol.
if (Len >= 4 && starts_with(Mangled, "__S")) {
const size_t SuffixLen = Mangled.length() - Len;
std::string_view P = Mangled.substr(3);
while (P.length() > SuffixLen && std::isdigit(P.front()))
P.remove_prefix(1);
if (P.length() == SuffixLen) {
if (Len >= 4 && Mangled[0] == '_' && Mangled[1] == '_' && Mangled[2] == 'S') {
const char *NumPtr = Mangled + 3;
while (NumPtr < (Mangled + Len) && std::isdigit(*NumPtr))
++NumPtr;
if (Mangled + Len == NumPtr) {
// Skip over the fake parent.
Mangled.remove_prefix(Len);
Mangled += Len;
return parseIdentifier(Demangled, Mangled);
}
// Else demangle it as a plain identifier.
}
parseLName(Demangled, Mangled, Len);
return parseLName(Demangled, Mangled, Len);
}
bool Demangler::parseType(std::string_view &Mangled) {
if (Mangled.empty()) {
Mangled = {};
return false;
}
const char *Demangler::parseType(const char *Mangled) {
if (*Mangled == '\0')
return nullptr;
switch (Mangled.front()) {
switch (*Mangled) {
// TODO: Parse type qualifiers.
// TODO: Parse function types.
// TODO: Parse compound types.
@@ -480,102 +464,102 @@ bool Demangler::parseType(std::string_view &Mangled) {
// Basic types.
case 'i':
Mangled.remove_prefix(1);
++Mangled;
// TODO: Add type name dumping
return true;
return Mangled;
// TODO: Add support for the rest of the basic types.
// Back referenced type.
case 'Q': {
parseTypeBackref(Mangled);
return true;
}
case 'Q':
return parseTypeBackref(Mangled);
default: // unhandled.
Mangled = {};
return false;
return nullptr;
}
}
void Demangler::parseLName(OutputBuffer *Demangled, std::string_view &Mangled,
unsigned long Len) {
const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled,
unsigned long Len) {
switch (Len) {
case 6:
if (starts_with(Mangled, "__initZ")) {
if (strncmp(Mangled, "__initZ", Len + 1) == 0) {
// The static initializer for a given symbol.
Demangled->prepend("initializer for ");
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
Mangled.remove_prefix(Len);
return;
Mangled += Len;
return Mangled;
}
if (starts_with(Mangled, "__vtblZ")) {
if (strncmp(Mangled, "__vtblZ", Len + 1) == 0) {
// The vtable symbol for a given class.
Demangled->prepend("vtable for ");
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
Mangled.remove_prefix(Len);
return;
Mangled += Len;
return Mangled;
}
break;
case 7:
if (starts_with(Mangled, "__ClassZ")) {
if (strncmp(Mangled, "__ClassZ", Len + 1) == 0) {
// The classinfo symbol for a given class.
Demangled->prepend("ClassInfo for ");
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
Mangled.remove_prefix(Len);
return;
Mangled += Len;
return Mangled;
}
break;
case 11:
if (starts_with(Mangled, "__InterfaceZ")) {
if (strncmp(Mangled, "__InterfaceZ", Len + 1) == 0) {
// The interface symbol for a given class.
Demangled->prepend("Interface for ");
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
Mangled.remove_prefix(Len);
return;
Mangled += Len;
return Mangled;
}
break;
case 12:
if (starts_with(Mangled, "__ModuleInfoZ")) {
if (strncmp(Mangled, "__ModuleInfoZ", Len + 1) == 0) {
// The ModuleInfo symbol for a given module.
Demangled->prepend("ModuleInfo for ");
Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1);
Mangled.remove_prefix(Len);
return;
Mangled += Len;
return Mangled;
}
break;
}
*Demangled << Mangled.substr(0, Len);
Mangled.remove_prefix(Len);
*Demangled << StringView(Mangled, Len);
Mangled += Len;
return Mangled;
}
Demangler::Demangler(std::string_view Mangled)
: Str(Mangled), LastBackref(Mangled.length()) {}
Demangler::Demangler(const char *Mangled)
: Str(Mangled), LastBackref(strlen(Mangled)) {}
const char *Demangler::parseMangle(OutputBuffer *Demangled) {
std::string_view M(this->Str);
parseMangle(Demangled, M);
return M.data();
return parseMangle(Demangled, this->Str);
}
char *llvm::dlangDemangle(std::string_view MangledName) {
if (MangledName.empty() || !starts_with(MangledName, "_D"))
char *llvm::dlangDemangle(const char *MangledName) {
if (MangledName == nullptr || strncmp(MangledName, "_D", 2) != 0)
return nullptr;
OutputBuffer Demangled;
if (MangledName == "_Dmain") {
if (!initializeOutputBuffer(nullptr, nullptr, Demangled, 1024))
return nullptr;
if (strcmp(MangledName, "_Dmain") == 0) {
Demangled << "D main";
} else {
Demangler D(MangledName);
const char *M = D.parseMangle(&Demangled);
Demangler D = Demangler(MangledName);
MangledName = D.parseMangle(&Demangled);
// Check that the entire symbol was successfully demangled.
if (M == nullptr || *M != '\0') {
if (MangledName == nullptr || *MangledName != '\0') {
std::free(Demangled.getBuffer());
return nullptr;
}

View File

@@ -11,45 +11,45 @@
//===----------------------------------------------------------------------===//
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/StringViewExtras.h"
#include <cstdlib>
#include <string_view>
#include <cstring>
using llvm::itanium_demangle::starts_with;
static bool isItaniumEncoding(const char *S) {
// Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'.
return std::strncmp(S, "_Z", 2) == 0 || std::strncmp(S, "___Z", 4) == 0;
}
std::string llvm::demangle(std::string_view MangledName) {
static bool isRustEncoding(const char *S) { return S[0] == '_' && S[1] == 'R'; }
static bool isDLangEncoding(const std::string &MangledName) {
return MangledName.size() >= 2 && MangledName[0] == '_' &&
MangledName[1] == 'D';
}
std::string llvm::demangle(const std::string &MangledName) {
std::string Result;
const char *S = MangledName.c_str();
if (nonMicrosoftDemangle(MangledName, Result))
if (nonMicrosoftDemangle(S, Result))
return Result;
if (starts_with(MangledName, '_') &&
nonMicrosoftDemangle(MangledName.substr(1), Result))
if (S[0] == '_' && nonMicrosoftDemangle(S + 1, Result))
return Result;
if (char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr)) {
if (char *Demangled =
microsoftDemangle(S, nullptr, nullptr, nullptr, nullptr)) {
Result = Demangled;
std::free(Demangled);
} else {
Result = MangledName;
return Result;
}
return Result;
return MangledName;
}
static bool isItaniumEncoding(std::string_view S) {
// Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'.
return starts_with(S, "_Z") || starts_with(S, "___Z");
}
static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); }
static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); }
bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
std::string &Result) {
bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) {
char *Demangled = nullptr;
if (isItaniumEncoding(MangledName))
Demangled = itaniumDemangle(MangledName);
Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr);
else if (isRustEncoding(MangledName))
Demangled = rustDemangle(MangledName);
else if (isDLangEncoding(MangledName))

View File

@@ -18,7 +18,6 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <functional>
#include <utility>
@@ -79,8 +78,8 @@ struct DumpVisitor {
}
void printStr(const char *S) { fprintf(stderr, "%s", S); }
void print(std::string_view SV) {
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data());
void print(StringView SV) {
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
}
void print(const Node *N) {
if (N)
@@ -366,21 +365,36 @@ public:
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
char *llvm::itaniumDemangle(std::string_view MangledName) {
if (MangledName.empty())
return nullptr;
Demangler Parser(MangledName.data(),
MangledName.data() + MangledName.length());
Node *AST = Parser.parse();
if (!AST)
char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
size_t *N, int *Status) {
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
if (Status)
*Status = demangle_invalid_args;
return nullptr;
}
int InternalStatus = demangle_success;
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
OutputBuffer OB;
assert(Parser.ForwardTemplateRefs.empty());
AST->print(OB);
OB += '\0';
return OB.getBuffer();
Node *AST = Parser.parse();
if (AST == nullptr)
InternalStatus = demangle_invalid_mangled_name;
else if (!initializeOutputBuffer(Buf, N, OB, 1024))
InternalStatus = demangle_memory_alloc_failure;
else {
assert(Parser.ForwardTemplateRefs.empty());
AST->print(OB);
OB += '\0';
if (N != nullptr)
*N = OB.getCurrentPosition();
Buf = OB.getBuffer();
}
if (Status)
*Status = InternalStatus;
return InternalStatus == demangle_success ? Buf : nullptr;
}
ItaniumPartialDemangler::ItaniumPartialDemangler()
@@ -413,7 +427,9 @@ bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
}
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
OutputBuffer OB(Buf, N);
OutputBuffer OB;
if (!initializeOutputBuffer(Buf, N, OB, 128))
return nullptr;
RootNode->print(OB);
OB += '\0';
if (N != nullptr)
@@ -456,7 +472,9 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
return nullptr;
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
OutputBuffer OB(Buf, N);
OutputBuffer OB;
if (!initializeOutputBuffer(Buf, N, OB, 128))
return nullptr;
KeepGoingLocalFunction:
while (true) {
@@ -507,7 +525,9 @@ char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
return nullptr;
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
OutputBuffer OB(Buf, N);
OutputBuffer OB;
if (!initializeOutputBuffer(Buf, N, OB, 128))
return nullptr;
OB += '(';
Params.printWithComma(OB);
@@ -523,7 +543,9 @@ char *ItaniumPartialDemangler::getFunctionReturnType(
if (!isFunction())
return nullptr;
OutputBuffer OB(Buf, N);
OutputBuffer OB;
if (!initializeOutputBuffer(Buf, N, OB, 128))
return nullptr;
if (const Node *Ret =
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())

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