Merge pull request #135 from madebr/update-202408

Get rid of conan, update imgui, and merge all workflows
This commit is contained in:
aap 2024-08-22 17:31:04 +02:00 committed by GitHub
commit 895556fd81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 21863 additions and 9377 deletions

View File

@ -1,57 +0,0 @@
name: Conan
on:
pull_request:
push:
release:
types: published
jobs:
build-cmake:
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
platform: ['null', 'gl3', 'd3d9']
gl3_gfxlib: ['glfw', 'sdl2']
exclude:
- os: ubuntu-latest
platform: d3d9
- os: macos-latest
platform: d3d9
- platform: 'null'
gl3_gfxlib: sdl2
- platform: d3d9
gl3_gfxlib: sdl2
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: "Setup conan"
run: |
python -m pip install conan
conan config init
- name: "Create host profile"
shell: bash
run: |
cp ~/.conan/profiles/default host_profile
- name: "Download/build dependencies (conan install)"
run: |
conan install ${{ github.workspace }} librw/master@ -if build -o librw:platform=${{ matrix.platform }} -o librw:gl3_gfxlib=${{ matrix.gl3_gfxlib }} --build missing -pr:h ./host_profile -pr:b default
env:
CONAN_SYSREQUIRES_MODE: enabled
- name: "Build librw (conan build)"
run: |
conan build ${{ github.workspace }} -if build -bf build -pf package
- name: "Package librw (conan package)"
run: |
conan package ${{ github.workspace }} -if build -bf build -pf package
- name: "Create binary package (cpack)"
working-directory: ./build
run: |
cpack
- name: "Archive binary package (github artifacts)"
uses: actions/upload-artifact@v2
with:
name: "${{ matrix.os }}-${{ matrix.platform }}"
path: build/*.tar.xz
if-no-files-found: error

View File

@ -1,29 +0,0 @@
name: Playstation 2 (by ps2dev)
on:
pull_request:
push:
release:
types: published
jobs:
build-playstation-2:
runs-on: ubuntu-latest
container: ps2dev/ps2dev
steps:
- uses: actions/checkout@v2
- name: "Install dependencies"
run: |
apk add build-base cmake
- name: "Build files"
run: |
cmake -S. -Bbuild -DLIBRW_INSTALL=ON -DLIBRW_PLATFORM=PS2 -DCMAKE_TOOLCHAIN_FILE=cmake/ps2/cmaketoolchain/toolchain_ps2_ee.cmake
cmake --build build --parallel
- name: "Create binary package (cpack)"
working-directory: ./build
run: |
cpack
- name: "Archive binary package (github artifacts)"
uses: actions/upload-artifact@v2
with:
name: "ps2"
path: build/*.tar.xz
if-no-files-found: error

View File

@ -1,26 +0,0 @@
name: Nintendo Switch (by devkitPro)
on:
pull_request:
push:
release:
types: published
jobs:
build-nintendo-switch:
runs-on: ubuntu-latest
container: devkitpro/devkita64:latest
steps:
- uses: actions/checkout@v2
- name: "Build files"
run: |
/opt/devkitpro/portlibs/switch/bin/aarch64-none-elf-cmake -S. -Bbuild -DLIBRW_PLATFORM=GL3 -DLIBRW_GL3_GFXLIB=GLFW -DLIBRW_INSTALL=True
cmake --build build --parallel
- name: "Create binary package (cpack)"
working-directory: ./build
run: |
cpack
- name: "Archive binary package (github artifacts)"
uses: actions/upload-artifact@v2
with:
name: "switch-gl3"
path: build/*.tar.xz
if-no-files-found: error

77
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,77 @@
name: Build
on:
pull_request:
push:
release:
types: published
jobs:
build-cmake:
name: ${{ matrix.case.name }}
runs-on: ${{ matrix.case.os }}
container: ${{ matrix.case.container }}
strategy:
fail-fast: false
matrix:
case:
- { name: 'Windows (DirectX 9)', os: 'windows-latest', platform: 'D3D9' }
- { name: 'Windows (GL3, glfw)', os: 'windows-latest', platform: 'GL3', gl3_gfxlib: 'GLFW' }
- { name: 'Windows (GL3, SDL2)', os: 'windows-latest', platform: 'GL3', gl3_gfxlib: 'SDL2' }
- { name: 'Windows (null)', os: 'windows-latest', platform: 'NULL' }
- { name: 'macOS (GL3, glfw)', os: 'macos-latest', platform: 'GL3', gl3_gfxlib: 'GLFW' }
- { name: 'macOS (GL3, SDL2)', os: 'macos-latest', platform: 'GL3', gl3_gfxlib: 'SDL2' }
- { name: 'macOS (null)', os: 'macos-latest', platform: 'NULL' }
- { name: 'Ubuntu (GL3, glfw)', os: 'ubuntu-latest', platform: 'GL3', gl3_gfxlib: 'GLFW' }
- { name: 'Ubuntu (GL3, SDL2)', os: 'ubuntu-latest', platform: 'GL3', gl3_gfxlib: 'SDL2' }
- { name: 'Ubuntu (null)', os: 'ubuntu-latest', platform: 'NULL' }
- { name: 'PlayStation 2', os: 'ubuntu-latest', platform: 'PS2', ps2: true, container: 'ps2dev/ps2dev:latest', cmake-toolchain-file: 'cmake/ps2/cmaketoolchain/toolchain_ps2_ee.cmake' }
- { name: 'Nintendo Switch', os: 'ubuntu-latest', platform: 'GL3', gl3_gfxlib: 'GLFW', glfw-nobuild: true, container: 'devkitpro/devkita64:latest', cmake-toolchain-file: '/opt/devkitpro/cmake/Switch.cmake' }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: 'Install PS2 dependencies'
if: ${{ matrix.case.ps2 }}
run: |
apk add cmake gmp mpc1 mpfr4 make pkgconf git
- name: 'Setup SDL2'
if: ${{ matrix.case.gl3_gfxlib == 'SDL2' }}
uses: libsdl-org/setup-sdl@main
with:
version: 2-latest
install-linux-dependencies: true
cmake-toolchain-file: ${{ matrix.case.cmake-toolchain-file }}
- name: 'Setup GLFW'
if: ${{ matrix.case.gl3_gfxlib == 'GLFW' && !matrix.case.glfw-nobuild }}
shell: sh
run: |
${{ (runner.os == 'Linux' && 'sudo apt-get update -y && sudo apt-get install -y libwayland-dev libxkbcommon-dev xorg-dev') || '' }}
git clone "https://github.com/glfw/glfw.git" glfw-source --depth 1
cmake -S glfw-source -B glfw-build -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF -DGLFW_BUILD_DOCS=OFF -DGLFW_INSTALL=ON -DCMAKE_INSTALL_PREFIX=glfw-prefix -DCMAKE_TOOLCHAIN_FILE="${{ matrix.case.cmake-toolchain-file }}" -DCMAKE_BUILD_TYPE=Release
cmake --build glfw-build --config Release
cmake --install glfw-build --config Release
echo "glfw3_ROOT=${{ github.workspace}}/glfw-prefix" >${GITHUB_ENV}
- name: 'Configure (CMake)'
shell: sh
run: |
cmake -S . -B build \
-DLIBRW_PLATFORM=${{ matrix.case.platform }} \
-DLIBRW_GL3_GFXLIB=${{ matrix.case.gl3_gfxlib }} \
-DCMAKE_TOOLCHAIN_FILE=${{ matrix.case.cmake-toolchain-file }} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POLICY_DEFAULT_CMP0074=NEW
- name: 'Build (CMake)'
run: |
cmake --build build --config Release --verbose
- name: 'Create binary package (CPack)'
run: |
cd build
cpack . -C Release
- name: 'Archive binary package (GitHub artifacts)'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.case.os }}-${{ matrix.case.platform }}${{ (matrix.case.gl3_gfxlib != '' && format('-{0}', matrix.case.gl3_gfxlib)) || '' }}
path: build/*.tar.xz
if-no-files-found: error

View File

@ -30,7 +30,7 @@ else()
set(LIBRW_PLATFORM_GL3_REQUIRES_OPENGL ON) set(LIBRW_PLATFORM_GL3_REQUIRES_OPENGL ON)
endif() endif()
list(GET LIBRW_PLATFORMS 0 LIBRW_PLATFORM_DEFAULT) list(GET LIBRW_PLATFORMS 0 LIBRW_PLATFORM_DEFAULT)
set(LIBRW_PLATFORM "${LIBRW_PLATFORM_DEFAULT}" CACHE STRING "Platform") set(LIBRW_PLATFORM "${LIBRW_PLATFORM_DEFAULT}" CACHE STRING "Platform (choices=${LIBRW_PLATFORMS})")
set_property(CACHE LIBRW_PLATFORM PROPERTY STRINGS ${LIBRW_PLATFORMS}) set_property(CACHE LIBRW_PLATFORM PROPERTY STRINGS ${LIBRW_PLATFORMS})
message(STATUS "LIBRW_PLATFORM = ${LIBRW_PLATFORM} (choices=${LIBRW_PLATFORMS})") message(STATUS "LIBRW_PLATFORM = ${LIBRW_PLATFORM} (choices=${LIBRW_PLATFORMS})")
set("LIBRW_PLATFORM_${LIBRW_PLATFORM}" ON) set("LIBRW_PLATFORM_${LIBRW_PLATFORM}" ON)
@ -38,14 +38,16 @@ if(NOT LIBRW_PLATFORM IN_LIST LIBRW_PLATFORMS)
message(FATAL_ERROR "Illegal LIBRW_PLATFORM=${LIBRW_PLATFORM}") message(FATAL_ERROR "Illegal LIBRW_PLATFORM=${LIBRW_PLATFORM}")
endif() endif()
set(LIBRW_GL3_GFXLIBS "GLFW" "SDL2")
set(LIBRW_GL3_GFXLIB "GLFW" CACHE STRING "gfxlib for gl3")
set_property(CACHE LIBRW_GL3_GFXLIB PROPERTY STRINGS ${LIBRW_GL3_GFXLIBS})
if(LIBRW_PLATFORM_GL3) if(LIBRW_PLATFORM_GL3)
set(LIBRW_GL3_GFXLIBS "GLFW" "SDL2")
set(LIBRW_GL3_GFXLIB "GLFW" CACHE STRING "gfxlib for gl3 (choices=${LIBRW_GL3_GFXLIBS})")
set_property(CACHE LIBRW_GL3_GFXLIB PROPERTY STRINGS ${LIBRW_GL3_GFXLIBS})
if(LIBRW_PLATFORM_GL3)
message(STATUS "LIBRW_GL3_GFXLIB = ${LIBRW_GL3_GFXLIB} (choices=${LIBRW_GL3_GFXLIBS})") message(STATUS "LIBRW_GL3_GFXLIB = ${LIBRW_GL3_GFXLIB} (choices=${LIBRW_GL3_GFXLIBS})")
endif() endif()
if(NOT LIBRW_GL3_GFXLIB IN_LIST LIBRW_GL3_GFXLIBS) if(NOT LIBRW_GL3_GFXLIB IN_LIST LIBRW_GL3_GFXLIBS)
message(FATAL_ERROR "Illegal LIBRW_GL3_GFXLIB=${LIBRW_GL3_GFXLIB}") message(FATAL_ERROR "Illegal LIBRW_GL3_GFXLIB=${LIBRW_GL3_GFXLIB}")
endif()
endif() endif()
if(LIBRW_PLATFORM_PS2) if(LIBRW_PLATFORM_PS2)

View File

@ -20,7 +20,10 @@ if(LIBRW_PLATFORM_GL3)
endif() endif()
elseif(LIBRW_GL3_GFXLIB STREQUAL "SDL2") elseif(LIBRW_GL3_GFXLIB STREQUAL "SDL2")
if (NOT TARGET SDL2::SDL2) if (NOT TARGET SDL2::SDL2)
find_package(SDL2 REQUIRED) find_package(SDL2 CONFIG)
if (NOT TARGET SDL2::SDL2)
find_package(SDL2 MODULE REQUIRED)
endif()
endif() endif()
endif() endif()
endif() endif()

View File

@ -1,132 +0,0 @@
from conans import ConanFile, CMake, tools
from conans.errors import ConanException, ConanInvalidConfiguration
import os
import shutil
import textwrap
class LibrwConan(ConanFile):
name = "librw"
version = "master"
license = "MIT"
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package"
options = {
"platform": ["null", "gl3", "d3d9", "ps2"],
"gl3_gfxlib": ["glfw", "sdl2"],
}
default_options = {
"platform": "gl3",
"gl3_gfxlib": "glfw",
"openal:with_external_libs": False,
"sdl2:vulkan": False,
"sdl2:opengl": True,
"sdl2:sdl2main": True,
}
no_copy_source = True
@property
def _os_is_playstation2(self):
try:
return self.settings.os == "Playstation2"
except ConanException:
return False
def config_options(self):
if self._os_is_playstation2:
self.options.platform = "ps2"
if self.settings.os == "Windows":
self.options.platform = "d3d9"
self.options["sdl2"].directx = False
def configure(self):
if self.options.platform != "gl3":
del self.options.gl3_gfxlib
def validate(self):
if self.options.platform == "d3d9" and self.settings.os != "Windows":
raise ConanInvalidConfiguration("platform=d3d9 can only be built for os=Windows")
if self._os_is_playstation2:
if self.options.platform not in ("null", "ps2"):
raise ConanInvalidConfiguration("os=Playstation2 only supports platform=(null,ps2)")
def requirements(self):
if self.options.platform == "gl3":
if self.options.gl3_gfxlib == "glfw":
self.requires("glfw/3.3.7")
elif self.options.gl3_gfxlib == "sdl2":
self.requires("sdl/2.0.20")
def export_sources(self):
for d in ("cmake", "skeleton", "src", "tools"):
shutil.copytree(src=d, dst=os.path.join(self.export_sources_folder, d))
self.copy("args.h")
self.copy("rw.h")
self.copy("CMakeLists.txt")
self.copy("LICENSE")
@property
def _librw_platform(self):
return {
"null": "NULL",
"gl3": "GL3",
"d3d9": "D3D9",
"ps2": "PS2",
}[str(self.options.platform)]
def build(self):
if self.source_folder == self.build_folder:
raise Exception("cannot build with source_folder == build_folder")
if self.options.platform == "gl3" and self.options.gl3_gfxlib == "glfw":
tools.save("Findglfw3.cmake",
textwrap.dedent(
"""
if(NOT TARGET glfw)
message(STATUS "Creating glfw TARGET")
add_library(glfw INTERFACE IMPORTED)
set_target_properties(glfw PROPERTIES
INTERFACE_LINK_LIBRARIES CONAN_PKG::glfw)
endif()
"""), append=True)
tools.save("CMakeLists.txt",
textwrap.dedent(
"""
cmake_minimum_required(VERSION 3.0)
project(cmake_wrapper)
include("{}/conanbuildinfo.cmake")
conan_basic_setup(TARGETS)
add_subdirectory("{}" librw)
""").format(self.install_folder.replace("\\", "/"),
self.source_folder.replace("\\", "/")))
cmake = CMake(self)
env = {}
cmake.definitions["LIBRW_PLATFORM"] = self._librw_platform
cmake.definitions["LIBRW_INSTALL"] = True
cmake.definitions["LIBRW_TOOLS"] = True
if self.options.platform == "gl3":
cmake.definitions["LIBRW_GL3_GFXLIB"] = str(self.options.gl3_gfxlib).upper()
if self._os_is_playstation2:
env["PS2SDK"] = self.deps_cpp_info["ps2dev-ps2sdk"].rootpath
with tools.environment_append(env):
cmake.configure(source_folder=self.build_folder)
cmake.build()
def package(self):
cmake = CMake(self)
cmake.install()
def package_info(self):
self.cpp_info.includedirs.append(os.path.join("include", "librw"))
self.cpp_info.libs = ["librw" if self.settings.compiler == "Visual Studio" else "rw"]
if self.options.platform == "null":
self.cpp_info.defines.append("RW_NULL")
elif self.options.platform == "gl3":
self.cpp_info.defines.append("RW_GL3")
if self.options.gl3_gfxlib == "sdl2":
self.cpp_info.defines.append("LIBRW_SDL2")
elif self.options.platform == "d3d9":
self.cpp_info.defines.append("RW_D3D9")
elif self.options.platform == "ps2":
self.cpp_info.defines.append("RW_PS2")

View File

@ -24,6 +24,7 @@ add_library(librw_skeleton
imgui/ImGuizmo.h imgui/ImGuizmo.h
) )
add_library(librw::skeleton ALIAS librw_skeleton) add_library(librw::skeleton ALIAS librw_skeleton)
target_compile_features(librw_skeleton PUBLIC cxx_std_11)
set_target_properties(librw_skeleton set_target_properties(librw_skeleton
PROPERTIES PROPERTIES
@ -37,6 +38,10 @@ target_link_libraries(librw_skeleton
librw librw
) )
if (LIBRW_GL3_GFXLIB STREQUAL "SDL2")
target_compile_definitions(librw_skeleton PRIVATE SDL_MAIN_HANDLED)
endif()
target_include_directories(librw_skeleton target_include_directories(librw_skeleton
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// https://github.com/CedricGuillemet/ImGuizmo // https://github.com/CedricGuillemet/ImGuizmo
// v 1.61 WIP // v 1.89 WIP
// //
// The MIT License(MIT) // The MIT License(MIT)
// //
@ -111,7 +111,11 @@ void EditTransform(const Camera& camera, matrix_t& matrix)
#define IMGUI_API #define IMGUI_API
#endif #endif
namespace ImGuizmo #ifndef IMGUIZMO_NAMESPACE
#define IMGUIZMO_NAMESPACE ImGuizmo
#endif
namespace IMGUIZMO_NAMESPACE
{ {
// call inside your own window and before Manipulate() in order to draw gizmo to that window. // call inside your own window and before Manipulate() in order to draw gizmo to that window.
// Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()). // Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()).
@ -132,6 +136,9 @@ namespace ImGuizmo
// return true if mouse IsOver or if the gizmo is in moving state // return true if mouse IsOver or if the gizmo is in moving state
IMGUI_API bool IsUsing(); IMGUI_API bool IsUsing();
// return true if any gizmo is in moving state
IMGUI_API bool IsUsingAny();
// enable/disable the gizmo. Stay in the state until next call to Enable. // enable/disable the gizmo. Stay in the state until next call to Enable.
// gizmo is rendered with gray half transparent color when disabled // gizmo is rendered with gray half transparent color when disabled
IMGUI_API void Enable(bool enable); IMGUI_API void Enable(bool enable);
@ -176,9 +183,15 @@ namespace ImGuizmo
SCALE_Y = (1u << 8), SCALE_Y = (1u << 8),
SCALE_Z = (1u << 9), SCALE_Z = (1u << 9),
BOUNDS = (1u << 10), BOUNDS = (1u << 10),
SCALE_XU = (1u << 11),
SCALE_YU = (1u << 12),
SCALE_ZU = (1u << 13),
TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z, TRANSLATE = TRANSLATE_X | TRANSLATE_Y | TRANSLATE_Z,
ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN, ROTATE = ROTATE_X | ROTATE_Y | ROTATE_Z | ROTATE_SCREEN,
SCALE = SCALE_X | SCALE_Y | SCALE_Z SCALE = SCALE_X | SCALE_Y | SCALE_Z,
SCALEU = SCALE_XU | SCALE_YU | SCALE_ZU, // universal
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
}; };
inline OPERATION operator|(OPERATION lhs, OPERATION rhs) inline OPERATION operator|(OPERATION lhs, OPERATION rhs)
@ -200,6 +213,9 @@ namespace ImGuizmo
// //
IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor); IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
// use this version if you did not call Manipulate before and you are just using ViewManipulate
IMGUI_API void ViewManipulate(float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
IMGUI_API void SetID(int id); IMGUI_API void SetID(int id);
// return true if the cursor is over the operation's gizmo // return true if the cursor is over the operation's gizmo
@ -210,4 +226,47 @@ namespace ImGuizmo
// When true (default), the guizmo axis flip for better visibility // When true (default), the guizmo axis flip for better visibility
// When false, they always stay along the positive world/local axis // When false, they always stay along the positive world/local axis
IMGUI_API void AllowAxisFlip(bool value); IMGUI_API void AllowAxisFlip(bool value);
// Configure the limit where axis are hidden
IMGUI_API void SetAxisLimit(float value);
// Configure the limit where planes are hiden
IMGUI_API void SetPlaneLimit(float value);
enum COLOR
{
DIRECTION_X, // directionColor[0]
DIRECTION_Y, // directionColor[1]
DIRECTION_Z, // directionColor[2]
PLANE_X, // planeColor[0]
PLANE_Y, // planeColor[1]
PLANE_Z, // planeColor[2]
SELECTION, // selectionColor
INACTIVE, // inactiveColor
TRANSLATION_LINE, // translationLineColor
SCALE_LINE,
ROTATION_USING_BORDER,
ROTATION_USING_FILL,
HATCHED_AXIS_LINES,
TEXT,
TEXT_SHADOW,
COUNT
};
struct Style
{
IMGUI_API Style();
float TranslationLineThickness; // Thickness of lines for translation gizmo
float TranslationLineArrowSize; // Size of arrow at the end of lines for translation gizmo
float RotationLineThickness; // Thickness of lines for rotation gizmo
float RotationOuterLineThickness; // Thickness of line surrounding the rotation gizmo
float ScaleLineThickness; // Thickness of lines for scale gizmo
float ScaleLineCircleSize; // Size of circle at the end of lines for scale gizmo
float HatchedAxisLineThickness; // Thickness of hatched axis lines
float CenterCircleSize; // Size of circle at the center of the translate/scale gizmo
ImVec4 Colors[COLOR::COUNT];
};
IMGUI_API Style& GetStyle();
} }

View File

@ -1,5 +1,5 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// COMPILE-TIME OPTIONS FOR DEAR IMGUI // DEAR IMGUI COMPILE-TIME OPTIONS
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -9,7 +9,7 @@
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#pragma once #pragma once
@ -21,56 +21,74 @@
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() // - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
//#define IMGUI_API __declspec( dllimport ) //#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
//---- Disable all of Dear ImGui or don't implement standard windows. //---- Disable all of Dear ImGui or don't implement standard windows/tools.
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty. //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements. //---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a) //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default io.PlatformOpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Enable Test Engine / Automation features.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
//---- Include imgui_user.h at the end of imgui.h as a convenience //---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H //#define IMGUI_INCLUDE_IMGUI_USER_H
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR //#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32 //#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
// #define IMGUI_USE_STB_SPRINTF //#define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'. // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE //#define IMGUI_ENABLE_FREETYPE
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
// Only works in combination with IMGUI_ENABLE_FREETYPE.
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
//---- Use stb_truetype to build and rasterize the font atlas (default) //---- Use stb_truetype to build and rasterize the font atlas (default)
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
//#define IMGUI_ENABLE_STB_TRUETYPE //#define IMGUI_ENABLE_STB_TRUETYPE
@ -79,13 +97,15 @@
// This will be inlined as part of ImVec2 and ImVec4 class declarations. // This will be inlined as part of ImVec2 and ImVec4 class declarations.
/* /*
#define IM_VEC2_CLASS_EXTRA \ #define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); } operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \ #define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); } operator MyVec4() const { return MyVec4(x,y,z,w); }
*/ */
//---- ...Or use Dear ImGui's own very basic math operators.
//#define IMGUI_DEFINE_MATH_OPERATORS
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
@ -99,23 +119,18 @@
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
//#define ImDrawCallback MyImDrawCallback //#define ImDrawCallback MyImDrawCallback
//---- Debug Tools: Macro to break in Debugger //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
//#define IM_DEBUG_BREAK IM_ASSERT(0) //#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak() //#define IM_DEBUG_BREAK __debugbreak()
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
// This adds a small runtime cost which is why it is not enabled by default.
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
//---- Debug Tools: Enable slower asserts //---- Debug Tools: Enable slower asserts
//#define IMGUI_DEBUG_PARANOID //#define IMGUI_DEBUG_PARANOID
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
/* /*
namespace ImGui namespace ImGui
{ {
void MyFunction(const char* name, const MyMatrix44& v); void MyFunction(const char* name, MyMatrix44* mtx);
} }
*/ */

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

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

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,19 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.00. // This is a slightly modified version of stb_rect_pack.h 1.01.
// Those changes would need to be pushed into nothings/stb:
// - Added STBRP__CDECL
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
//
// stb_rect_pack.h - v1.00 - public domain - rectangle packing // stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014 // Sean Barrett 2014
// //
// Useful for e.g. packing rectangular textures into an atlas. // Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation. // Does not do rotation.
// //
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than // Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what // the totally naive one in stb_truetype (which is primarily what
// this is meant to replace). // this is meant to replace).
@ -41,6 +45,7 @@
// //
// Version history: // Version history:
// //
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes // 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result // 0.11 (2017-03-03) return packing success/fail result
@ -81,11 +86,10 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node; typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect; typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord; typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord; #define STBRP__MAXVAL 0x7fffffff
#endif // Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type // Assign packed locations to rectangles. The rectangles are of type
@ -213,7 +217,6 @@ struct stbrp_context
#define STBRP_ASSERT assert #define STBRP_ASSERT assert
#endif #endif
// [DEAR IMGUI] Added STBRP__CDECL
#ifdef _MSC_VER #ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v) #define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl #define STBRP__CDECL __cdecl
@ -262,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{ {
int i; int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i) for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1]; nodes[i].next = &nodes[i+1];
@ -283,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0; context->extra[0].y = 0;
context->extra[0].next = &context->extra[1]; context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width; context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30); context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL; context->extra[1].next = NULL;
} }
@ -433,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
if (y <= best_y) { if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos; best_x = xpos;
STBRP_ASSERT(y <= best_y); //STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
best_y = y; best_y = y;
best_waste = waste; best_waste = waste;
best = prev; best = prev;
@ -529,7 +525,6 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res; return res;
} }
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_height_compare(const void *a, const void *b) static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{ {
const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *p = (const stbrp_rect *) a;
@ -541,7 +536,6 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w); return (p->w > q->w) ? -1 : (p->w < q->w);
} }
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_original_order(const void *a, const void *b) static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{ {
const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *p = (const stbrp_rect *) a;
@ -549,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b)
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
} }
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{ {
int i, all_rects_packed = 1; int i, all_rects_packed = 1;

View File

@ -1,10 +1,12 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_textedit.h 1.13. // This is a slightly modified version of stb_textedit.h 1.14.
// Those changes would need to be pushed into nothings/stb: // Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
// stb_textedit.h - v1.13 - public domain - Sean Barrett // stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools // Development of this library was sponsored by RAD Game Tools
// //
// This C header file implements the guts of a multi-line text-editing // This C header file implements the guts of a multi-line text-editing
@ -29,16 +31,17 @@
// DEPENDENCIES // DEPENDENCIES
// //
// Uses the C runtime function 'memmove', which you can override // Uses the C runtime function 'memmove', which you can override
// by defining STB_TEXTEDIT_memmove before the implementation. // by defining IMSTB_TEXTEDIT_memmove before the implementation.
// Uses no other functions. Performs no runtime allocations. // Uses no other functions. Performs no runtime allocations.
// //
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.14 (2021-07-11) page up/down, various fixes
// 1.13 (2019-02-07) fix bug in undo size management // 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
// 1.9 (2016-08-27) customizable move-by-word // 1.9 (2016-08-27) customizable move-by-word
// 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.8 (2016-04-02) better keyboard handling when mouse button is down
// 1.7 (2015-09-13) change y range handling in case baseline is non-0 // 1.7 (2015-09-13) change y range handling in case baseline is non-0
@ -58,6 +61,7 @@
// Ulf Winklemann: move-by-word in 1.1 // Ulf Winklemann: move-by-word in 1.1
// Fabian Giesen: secondary key inputs in 1.5 // Fabian Giesen: secondary key inputs in 1.5
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
// Louis Schnellbach: page up/down in 1.14
// //
// Bugfixes: // Bugfixes:
// Scott Graham // Scott Graham
@ -93,8 +97,8 @@
// moderate sizes. The undo system does no memory allocations, so // moderate sizes. The undo system does no memory allocations, so
// it grows STB_TexteditState by the worst-case storage which is (in bytes): // it grows STB_TexteditState by the worst-case storage which is (in bytes):
// //
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT // [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
// //
// //
// Implementation mode: // Implementation mode:
@ -271,8 +275,8 @@
//// ////
//// ////
#ifndef INCLUDE_STB_TEXTEDIT_H #ifndef INCLUDE_IMSTB_TEXTEDIT_H
#define INCLUDE_STB_TEXTEDIT_H #define INCLUDE_IMSTB_TEXTEDIT_H
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
@ -283,33 +287,33 @@
// and undo state. // and undo state.
// //
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT #ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
#define STB_TEXTEDIT_UNDOSTATECOUNT 99 #define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
#endif #endif
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT #ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
#define STB_TEXTEDIT_UNDOCHARCOUNT 999 #define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
#endif #endif
#ifndef STB_TEXTEDIT_CHARTYPE #ifndef IMSTB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_CHARTYPE int #define IMSTB_TEXTEDIT_CHARTYPE int
#endif #endif
#ifndef STB_TEXTEDIT_POSITIONTYPE #ifndef IMSTB_TEXTEDIT_POSITIONTYPE
#define STB_TEXTEDIT_POSITIONTYPE int #define IMSTB_TEXTEDIT_POSITIONTYPE int
#endif #endif
typedef struct typedef struct
{ {
// private data // private data
STB_TEXTEDIT_POSITIONTYPE where; IMSTB_TEXTEDIT_POSITIONTYPE where;
STB_TEXTEDIT_POSITIONTYPE insert_length; IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
STB_TEXTEDIT_POSITIONTYPE delete_length; IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
int char_storage; int char_storage;
} StbUndoRecord; } StbUndoRecord;
typedef struct typedef struct
{ {
// private data // private data
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
short undo_point, redo_point; short undo_point, redo_point;
int undo_char_point, redo_char_point; int undo_char_point, redo_char_point;
} StbUndoState; } StbUndoState;
@ -368,7 +372,7 @@ typedef struct
float ymin,ymax; // height of row above and below baseline float ymin,ymax; // height of row above and below baseline
int num_chars; int num_chars;
} StbTexteditRow; } StbTexteditRow;
#endif //INCLUDE_STB_TEXTEDIT_H #endif //INCLUDE_IMSTB_TEXTEDIT_H
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -381,11 +385,11 @@ typedef struct
// implementation isn't include-guarded, since it might have indirectly // implementation isn't include-guarded, since it might have indirectly
// included just the "header" portion // included just the "header" portion
#ifdef STB_TEXTEDIT_IMPLEMENTATION #ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
#ifndef STB_TEXTEDIT_memmove #ifndef IMSTB_TEXTEDIT_memmove
#include <string.h> #include <string.h>
#define STB_TEXTEDIT_memmove memmove #define IMSTB_TEXTEDIT_memmove memmove
#endif #endif
@ -395,7 +399,7 @@ typedef struct
// //
// traverse the layout to locate the nearest character to a display position // traverse the layout to locate the nearest character to a display position
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
{ {
StbTexteditRow r; StbTexteditRow r;
int n = STB_TEXTEDIT_STRINGLEN(str); int n = STB_TEXTEDIT_STRINGLEN(str);
@ -455,7 +459,7 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
} }
// API click: on mouse down, move the cursor to the clicked location, and reset the selection // API click: on mouse down, move the cursor to the clicked location, and reset the selection
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{ {
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
// goes off the top or bottom of the text // goes off the top or bottom of the text
@ -473,7 +477,7 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
} }
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{ {
int p = 0; int p = 0;
@ -499,11 +503,11 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
// //
// forward declarations // forward declarations
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
typedef struct typedef struct
{ {
@ -515,36 +519,21 @@ typedef struct
// find the x/y location of a character, and remember info about the previous row in // find the x/y location of a character, and remember info about the previous row in
// case we get a move-up event (for page up, we'll have to rescan) // case we get a move-up event (for page up, we'll have to rescan)
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line) static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line)
{ {
StbTexteditRow r; StbTexteditRow r;
int prev_start = 0; int prev_start = 0;
int z = STB_TEXTEDIT_STRINGLEN(str); int z = STB_TEXTEDIT_STRINGLEN(str);
int i=0, first; int i=0, first;
if (n == z) { if (n == z && single_line) {
// if it's at the end, then find the last line -- simpler than trying to // special case if it's at the end (may not be needed?)
// explicitly handle this case in the regular code
if (single_line) {
STB_TEXTEDIT_LAYOUTROW(&r, str, 0); STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
find->y = 0; find->y = 0;
find->first_char = 0; find->first_char = 0;
find->length = z; find->length = z;
find->height = r.ymax - r.ymin; find->height = r.ymax - r.ymin;
find->x = r.x1; find->x = r.x1;
} else {
find->y = 0;
find->x = 0;
find->height = 1;
while (i < z) {
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
prev_start = i;
i += r.num_chars;
}
find->first_char = i;
find->length = 0;
find->prev_first = prev_start;
}
return; return;
} }
@ -555,9 +544,16 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
STB_TEXTEDIT_LAYOUTROW(&r, str, i); STB_TEXTEDIT_LAYOUTROW(&r, str, i);
if (n < i + r.num_chars) if (n < i + r.num_chars)
break; break;
if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line
break; // [DEAR IMGUI]
prev_start = i; prev_start = i;
i += r.num_chars; i += r.num_chars;
find->y += r.baseline_y_delta; find->y += r.baseline_y_delta;
if (i == z) // [DEAR IMGUI]
{
r.num_chars = 0; // [DEAR IMGUI]
break; // [DEAR IMGUI]
}
} }
find->first_char = first = i; find->first_char = first = i;
@ -574,7 +570,7 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
// make the selection/cursor state valid if client altered the string // make the selection/cursor state valid if client altered the string
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
int n = STB_TEXTEDIT_STRINGLEN(str); int n = STB_TEXTEDIT_STRINGLEN(str);
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
@ -588,7 +584,7 @@ static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
} }
// delete characters while updating undo // delete characters while updating undo
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
{ {
stb_text_makeundo_delete(str, state, where, len); stb_text_makeundo_delete(str, state, where, len);
STB_TEXTEDIT_DELETECHARS(str, where, len); STB_TEXTEDIT_DELETECHARS(str, where, len);
@ -596,7 +592,7 @@ static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *sta
} }
// delete the section // delete the section
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
@ -633,7 +629,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
} }
// move cursor to last character of selection // move cursor to last character of selection
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(state); stb_textedit_sortselection(state);
@ -645,13 +641,13 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
} }
#ifdef STB_TEXTEDIT_IS_SPACE #ifdef STB_TEXTEDIT_IS_SPACE
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx ) static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
{ {
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
} }
#ifndef STB_TEXTEDIT_MOVEWORDLEFT #ifndef STB_TEXTEDIT_MOVEWORDLEFT
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
{ {
--c; // always move at least one character --c; // always move at least one character
while( c >= 0 && !is_word_boundary( str, c ) ) while( c >= 0 && !is_word_boundary( str, c ) )
@ -666,7 +662,7 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
#endif #endif
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT #ifndef STB_TEXTEDIT_MOVEWORDRIGHT
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
{ {
const int len = STB_TEXTEDIT_STRINGLEN(str); const int len = STB_TEXTEDIT_STRINGLEN(str);
++c; // always move at least one character ++c; // always move at least one character
@ -693,7 +689,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
} }
// API cut: delete selection // API cut: delete selection
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state); // implicitly clamps stb_textedit_delete_selection(str,state); // implicitly clamps
@ -704,7 +700,7 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
} }
// API paste: replace existing selection with passed-in text // API paste: replace existing selection with passed-in text
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len)
{ {
// if there's a selection, the paste should delete it // if there's a selection, the paste should delete it
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
@ -716,9 +712,7 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
state->has_preferred_x = 0; state->has_preferred_x = 0;
return 1; return 1;
} }
// remove the undo since we didn't actually insert the characters // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
if (state->undostate.undo_point)
--state->undostate.undo_point;
return 0; return 0;
} }
@ -727,14 +721,14 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
#endif #endif
// API key: process a keyboard input // API key: process a keyboard input
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
{ {
retry: retry:
switch (key) { switch (key) {
default: { default: {
int c = STB_TEXTEDIT_KEYTOTEXT(key); int c = STB_TEXTEDIT_KEYTOTEXT(key);
if (c > 0) { if (c > 0) {
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c; IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c;
// can't add newline in single-line mode // can't add newline in single-line mode
if (c == '\n' && state->single_line) if (c == '\n' && state->single_line)
@ -899,8 +893,8 @@ retry:
x = row.x0; x = row.x0;
for (i=0; i < row.num_chars; ++i) { for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE #ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break; break;
#endif #endif
x += dx; x += dx;
@ -961,8 +955,8 @@ retry:
x = row.x0; x = row.x0;
for (i=0; i < row.num_chars; ++i) { for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE #ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
break; break;
#endif #endif
x += dx; x += dx;
@ -1119,8 +1113,8 @@ retry:
static void stb_textedit_flush_redo(StbUndoState *state) static void stb_textedit_flush_redo(StbUndoState *state)
{ {
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
} }
// discard the oldest entry in the undo list // discard the oldest entry in the undo list
@ -1132,13 +1126,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
int n = state->undo_rec[0].insert_length, i; int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records // delete n characters from all other records
state->undo_char_point -= n; state->undo_char_point -= n;
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i) for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0) if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
} }
--state->undo_point; --state->undo_point;
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
} }
} }
@ -1148,7 +1142,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
// fill up even though the undo buffer didn't // fill up even though the undo buffer didn't
static void stb_textedit_discard_redo(StbUndoState *state) static void stb_textedit_discard_redo(StbUndoState *state)
{ {
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1; int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1;
if (state->redo_point <= k) { if (state->redo_point <= k) {
// if the k'th undo state has characters, clean those up // if the k'th undo state has characters, clean those up
@ -1156,7 +1150,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
int n = state->undo_rec[k].insert_length, i; int n = state->undo_rec[k].insert_length, i;
// move the remaining redo character data to the end of the buffer // move the remaining redo character data to the end of the buffer
state->redo_char_point += n; state->redo_char_point += n;
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
// adjust the position of all the other records to account for above memmove // adjust the position of all the other records to account for above memmove
for (i=state->redo_point; i < k; ++i) for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0) if (state->undo_rec[i].char_storage >= 0)
@ -1164,12 +1158,12 @@ static void stb_textedit_discard_redo(StbUndoState *state)
} }
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point' // now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
// [DEAR IMGUI] // [DEAR IMGUI]
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size); IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
// now move redo_point to point to the new one // now move redo_point to point to the new one
++state->redo_point; ++state->redo_point;
@ -1183,32 +1177,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
// if we have no free records, we have to make room, by sliding the // if we have no free records, we have to make room, by sliding the
// existing records down // existing records down
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
stb_textedit_discard_undo(state); stb_textedit_discard_undo(state);
// if the characters to store won't possibly fit in the buffer, we can't undo // if the characters to store won't possibly fit in the buffer, we can't undo
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
state->undo_point = 0; state->undo_point = 0;
state->undo_char_point = 0; state->undo_char_point = 0;
return NULL; return NULL;
} }
// if we don't have enough free characters in the buffer, we have to make room // if we don't have enough free characters in the buffer, we have to make room
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT)
stb_textedit_discard_undo(state); stb_textedit_discard_undo(state);
return &state->undo_rec[state->undo_point++]; return &state->undo_rec[state->undo_point++];
} }
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
{ {
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
if (r == NULL) if (r == NULL)
return NULL; return NULL;
r->where = pos; r->where = pos;
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
if (insert_len == 0) { if (insert_len == 0) {
r->char_storage = -1; r->char_storage = -1;
@ -1220,7 +1214,7 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos,
} }
} }
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
StbUndoState *s = &state->undostate; StbUndoState *s = &state->undostate;
StbUndoRecord u, *r; StbUndoRecord u, *r;
@ -1247,7 +1241,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// characters stored for *undoing* don't leave room for redo // characters stored for *undoing* don't leave room for redo
// if the last is true, we have to bail // if the last is true, we have to bail
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
// the undo records take up too much character space; there's no space to store the redo characters // the undo records take up too much character space; there's no space to store the redo characters
r->insert_length = 0; r->insert_length = 0;
} else { } else {
@ -1256,7 +1250,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// there's definitely room to store the characters eventually // there's definitely room to store the characters eventually
while (s->undo_char_point + u.delete_length > s->redo_char_point) { while (s->undo_char_point + u.delete_length > s->redo_char_point) {
// should never happen: // should never happen:
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return; return;
// there's currently not enough room, so discard a redo record // there's currently not enough room, so discard a redo record
stb_textedit_discard_redo(s); stb_textedit_discard_redo(s);
@ -1288,11 +1282,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
s->redo_point--; s->redo_point--;
} }
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
StbUndoState *s = &state->undostate; StbUndoState *s = &state->undostate;
StbUndoRecord *u, r; StbUndoRecord *u, r;
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
return; return;
// we need to do two things: apply the redo record, and create an undo record // we need to do two things: apply the redo record, and create an undo record
@ -1344,20 +1338,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
stb_text_createundo(&state->undostate, where, 0, length); stb_text_createundo(&state->undostate, where, 0, length);
} }
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
{ {
int i; int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
if (p) { if (p) {
for (i=0; i < length; ++i) for (i=0; i < length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
} }
} }
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
{ {
int i; int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
if (p) { if (p) {
for (i=0; i < old_length; ++i) for (i=0; i < old_length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
@ -1369,8 +1363,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
{ {
state->undostate.undo_point = 0; state->undostate.undo_point = 0;
state->undostate.undo_char_point = 0; state->undostate.undo_char_point = 0;
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
state->select_end = state->select_start = 0; state->select_end = state->select_start = 0;
state->cursor = 0; state->cursor = 0;
state->has_preferred_x = 0; state->has_preferred_x = 0;
@ -1393,16 +1387,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
#pragma GCC diagnostic ignored "-Wcast-qual" #pragma GCC diagnostic ignored "-Wcast-qual"
#endif #endif
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len)
{ {
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len);
} }
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#endif//STB_TEXTEDIT_IMPLEMENTATION #endif//IMSTB_TEXTEDIT_IMPLEMENTATION
/* /*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View File

@ -1,10 +1,19 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_truetype.h 1.20. // This is a slightly modified version of stb_truetype.h 1.26.
// Mostly fixing for compiler and static analyzer warnings. // Mostly fixing for compiler and static analyzer warnings.
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
// stb_truetype.h - v1.20 - public domain // stb_truetype.h - v1.26 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools // authored from 2009-2021 by Sean Barrett / RAD Game Tools
//
// =======================================================================
//
// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
//
// This library does no range checking of the offsets found in the file,
// meaning an attacker can use it to read arbitrary memory.
//
// =======================================================================
// //
// This library processes TrueType files: // This library processes TrueType files:
// parse files // parse files
@ -37,11 +46,11 @@
// Daniel Ribeiro Maciel // Daniel Ribeiro Maciel
// //
// Bug/warning reports/fixes: // Bug/warning reports/fixes:
// "Zer" on mollyrocket Fabian "ryg" Giesen // "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
// Cass Everitt Martins Mozeiko // Cass Everitt Martins Mozeiko github:aloucks
// stoiko (Haemimont Games) Cap Petschulat // stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
// Brian Hook Omar Cornut // Brian Hook Omar Cornut github:vassvik
// Walter van Niftrik github:aloucks // Walter van Niftrik Ryan Griege
// David Gow Peter LaValle // David Gow Peter LaValle
// David Given Sergey Popov // David Given Sergey Popov
// Ivan-Assen Ivanov Giumo X. Clanjor // Ivan-Assen Ivanov Giumo X. Clanjor
@ -49,11 +58,17 @@
// Johan Duparc Thomas Fields // Johan Duparc Thomas Fields
// Hou Qiming Derek Vinyard // Hou Qiming Derek Vinyard
// Rob Loach Cort Stratton // Rob Loach Cort Stratton
// Kenney Phillis Jr. github:oyvindjam // Kenney Phillis Jr. Brian Costabile
// Brian Costabile github:vassvik // Ken Voskuil (kaesve)
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.26 (2021-08-28) fix broken rasterizer
// 1.25 (2021-07-11) many fixes
// 1.24 (2020-02-05) fix warning
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
// 1.21 (2019-02-25) fix warning
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
// 1.18 (2018-01-29) add missing function // 1.18 (2018-01-29) add missing function
@ -248,19 +263,6 @@
// recommend it. // recommend it.
// //
// //
// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
//
// Documentation & header file 520 LOC \___ 660 LOC documentation
// Sample code 140 LOC /
// Truetype parsing 620 LOC ---- 620 LOC TrueType
// Software rasterization 240 LOC \.
// Curve tessellation 120 LOC \__ 550 LOC Bitmap creation
// Bitmap management 100 LOC /
// Baked bitmap interface 70 LOC /
// Font name matching & access 150 LOC ---- 150
// C runtime library abstraction 60 LOC ---- 60
//
//
// PERFORMANCE MEASUREMENTS FOR 1.06: // PERFORMANCE MEASUREMENTS FOR 1.06:
// //
// 32-bit 64-bit // 32-bit 64-bit
@ -275,8 +277,8 @@
//// SAMPLE PROGRAMS //// SAMPLE PROGRAMS
//// ////
// //
// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
// // See "tests/truetype_demo_win32.c" for a complete version.
#if 0 #if 0
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
#include "stb_truetype.h" #include "stb_truetype.h"
@ -302,6 +304,8 @@ void my_stbtt_initfont(void)
void my_stbtt_print(float x, float y, char *text) void my_stbtt_print(float x, float y, char *text)
{ {
// assume orthographic projection with units = screen pixels, origin at top left // assume orthographic projection with units = screen pixels, origin at top left
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, ftex); glBindTexture(GL_TEXTURE_2D, ftex);
glBegin(GL_QUADS); glBegin(GL_QUADS);
@ -309,10 +313,10 @@ void my_stbtt_print(float x, float y, char *text)
if (*text >= 32 && *text < 128) { if (*text >= 32 && *text < 128) {
stbtt_aligned_quad q; stbtt_aligned_quad q;
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
} }
++text; ++text;
} }
@ -652,7 +656,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which // If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then // there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph, // codepoints without a glyph received the font's "missing character" glyph,
// typically an empty box by convention. // typically an empty box by convention.
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
@ -719,7 +723,7 @@ struct stbtt_fontinfo
int numGlyphs; // number of glyphs, needed for range checking int numGlyphs; // number of glyphs, needed for range checking
int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph int indexToLocFormat; // format needed to map from glyph index to glyph
@ -802,6 +806,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
// as above, but takes one or more glyph indices for greater efficiency // as above, but takes one or more glyph indices for greater efficiency
typedef struct stbtt_kerningentry
{
int glyph1; // use stbtt_FindGlyphIndex
int glyph2;
int advance;
} stbtt_kerningentry;
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
// Retrieves a complete list of all of the kerning pairs provided by the font
// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -846,6 +862,12 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
// frees the data allocated above // frees the data allocated above
STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
// fills svg with the character's SVG data.
// returns data size or 0 if SVG not found.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// BITMAP RENDERING // BITMAP RENDERING
@ -1347,6 +1369,22 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
return stbtt__cff_get_index(&cff); return stbtt__cff_get_index(&cff);
} }
// since most people won't use this, find this table the first time it's needed
static int stbtt__get_svg(stbtt_fontinfo *info)
{
stbtt_uint32 t;
if (info->svg < 0) {
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
if (t) {
stbtt_uint32 offset = ttULONG(info->data + t + 2);
info->svg = t + offset;
} else {
info->svg = 0;
}
}
return info->svg;
}
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
{ {
stbtt_uint32 cmap, t; stbtt_uint32 cmap, t;
@ -1426,6 +1464,8 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
else else
info->numGlyphs = 0xffff; info->numGlyphs = 0xffff;
info->svg = -1;
// find a cmap encoding table we understand *now* to avoid searching // find a cmap encoding table we understand *now* to avoid searching
// later. (todo: could make this installable) // later. (todo: could make this installable)
// the same regardless of glyph. // the same regardless of glyph.
@ -1509,12 +1549,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
search += 2; search += 2;
{ {
stbtt_uint16 offset, start; stbtt_uint16 offset, start, last;
stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
if (unicode_codepoint < start) last = ttUSHORT(data + endCount + 2*item);
if (unicode_codepoint < start || unicode_codepoint > last)
return 0; return 0;
offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
@ -1774,7 +1814,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
} }
} }
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
} else if (numberOfContours == -1) { } else if (numberOfContours < 0) {
// Compound shapes. // Compound shapes.
int more = 1; int more = 1;
stbtt_uint8 *comp = data + g + 10; stbtt_uint8 *comp = data + g + 10;
@ -1841,7 +1881,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
if (comp_verts) STBTT_free(comp_verts, info->userdata); if (comp_verts) STBTT_free(comp_verts, info->userdata);
return 0; return 0;
} }
if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595 if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
if (vertices) STBTT_free(vertices, info->userdata); if (vertices) STBTT_free(vertices, info->userdata);
vertices = tmp; vertices = tmp;
@ -1851,9 +1891,6 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
// More components ? // More components ?
more = flags & (1<<5); more = flags & (1<<5);
} }
} else if (numberOfContours < 0) {
// @TODO other compound variations?
STBTT_assert(0);
} else { } else {
// numberOfCounters == 0, do nothing // numberOfCounters == 0, do nothing
} }
@ -1971,7 +2008,7 @@ static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int gly
start = end; start = end;
} }
} }
if (fdselector == -1) stbtt__new_buf(NULL, 0); if (fdselector == -1) return stbtt__new_buf(NULL, 0); // [DEAR IMGUI] fixed, see #6007 and nothings/stb#1422
return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
} }
@ -2107,7 +2144,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
has_subrs = 1; has_subrs = 1;
} }
// fallthrough // FALLTHROUGH
case 0x1D: // callgsubr case 0x1D: // callgsubr
if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
v = (int) s[--sp]; v = (int) s[--sp];
@ -2212,7 +2249,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
} break; } break;
default: default:
if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560 if (b0 != 255 && b0 != 28 && b0 < 32)
return STBTT__CSERR("reserved operator"); return STBTT__CSERR("reserved operator");
// push immediate // push immediate
@ -2282,6 +2319,48 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
} }
} }
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
{
stbtt_uint8 *data = info->data + info->kern;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
return ttUSHORT(data+10);
}
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
{
stbtt_uint8 *data = info->data + info->kern;
int k, length;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
length = ttUSHORT(data+10);
if (table_length < length)
length = table_length;
for (k = 0; k < length; k++)
{
table[k].glyph1 = ttUSHORT(data+18+(k*6));
table[k].glyph2 = ttUSHORT(data+20+(k*6));
table[k].advance = ttSHORT(data+22+(k*6));
}
return length;
}
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{ {
stbtt_uint8 *data = info->data + info->kern; stbtt_uint8 *data = info->data + info->kern;
@ -2315,7 +2394,7 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
{ {
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
switch(coverageFormat) { switch (coverageFormat) {
case 1: { case 1: {
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
@ -2336,7 +2415,8 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp
return m; return m;
} }
} }
} break; break;
}
case 2: { case 2: {
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
@ -2360,12 +2440,10 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp
return startCoverageIndex + glyph - strawStart; return startCoverageIndex + glyph - strawStart;
} }
} }
} break; break;
}
default: { default: return -1; // unsupported
// There are no other cases.
STBTT_assert(0);
} break;
} }
return -1; return -1;
@ -2374,7 +2452,7 @@ static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyp
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
{ {
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
switch(classDefFormat) switch (classDefFormat)
{ {
case 1: { case 1: {
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
@ -2383,10 +2461,8 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
break;
// [DEAR IMGUI] Commented to fix static analyzer warning }
//classDefTable = classDef1ValueArray + 2 * glyphCount;
} break;
case 2: { case 2: {
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
@ -2408,18 +2484,15 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
else else
return (stbtt_int32)ttUSHORT(classRangeRecord + 4); return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
} }
break;
// [DEAR IMGUI] Commented to fix static analyzer warning
//classDefTable = classRangeRecords + 6 * classRangeCount;
} break;
default: {
// There are no other cases.
STBTT_assert(0);
} break;
} }
return -1; default:
return -1; // Unsupported definition type, return an error.
}
// "All glyphs not assigned to a class fall into class 0". (OpenType spec)
return 0;
} }
// Define to STBTT_assert(x) if you want to break on unimplemented formats. // Define to STBTT_assert(x) if you want to break on unimplemented formats.
@ -2431,7 +2504,7 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
stbtt_uint8 *lookupList; stbtt_uint8 *lookupList;
stbtt_uint16 lookupCount; stbtt_uint16 lookupCount;
stbtt_uint8 *data; stbtt_uint8 *data;
stbtt_int32 i; stbtt_int32 i, sti;
if (!info->gpos) return 0; if (!info->gpos) return 0;
@ -2451,9 +2524,9 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
stbtt_uint16 lookupType = ttUSHORT(lookupTable); stbtt_uint16 lookupType = ttUSHORT(lookupTable);
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4); stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
stbtt_uint8 *subTableOffsets = lookupTable + 6; stbtt_uint8 *subTableOffsets = lookupTable + 6;
switch(lookupType) { if (lookupType != 2) // Pair Adjustment Positioning Subtable
case 2: { // Pair Adjustment Positioning Subtable continue;
stbtt_int32 sti;
for (sti=0; sti<subTableCount; sti++) { for (sti=0; sti<subTableCount; sti++) {
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti); stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
stbtt_uint8 *table = lookupTable + subtableOffset; stbtt_uint8 *table = lookupTable + subtableOffset;
@ -2468,20 +2541,15 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
int straw, needle; int straw, needle;
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
stbtt_int32 valueRecordPairSizeInBytes = 2; stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8); stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex); stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
stbtt_uint8 *pairValueTable = table + pairPosOffset; stbtt_uint8 *pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable); stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
stbtt_uint8 *pairValueArray = pairValueTable + 2; stbtt_uint8 *pairValueArray = pairValueTable + 2;
// TODO: Support more formats.
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
if (valueFormat1 != 4) return 0;
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
if (valueFormat2 != 0) return 0;
STBTT_assert(coverageIndex < pairSetCount); if (coverageIndex >= pairSetCount) return 0;
STBTT__NOTUSED(pairSetCount);
needle=glyph2; needle=glyph2;
r=pairValueCount-1; r=pairValueCount-1;
@ -2504,12 +2572,15 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
return xAdvance; return xAdvance;
} }
} }
} break; } else
return 0;
break;
}
case 2: { case 2: {
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
@ -2517,36 +2588,24 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
stbtt_uint16 class1Count = ttUSHORT(table + 12); stbtt_uint16 class1Count = ttUSHORT(table + 12);
stbtt_uint16 class2Count = ttUSHORT(table + 14); stbtt_uint16 class2Count = ttUSHORT(table + 14);
STBTT_assert(glyph1class < class1Count); stbtt_uint8 *class1Records, *class2Records;
STBTT_assert(glyph2class < class2Count); stbtt_int16 xAdvance;
// TODO: Support more formats. if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
STBTT_GPOS_TODO_assert(valueFormat1 == 4); if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
if (valueFormat1 != 4) return 0;
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
if (valueFormat2 != 0) return 0;
if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { class1Records = table + 16;
stbtt_uint8 *class1Records = table + 16; class2Records = class1Records + 2 * (glyph1class * class2Count);
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); xAdvance = ttSHORT(class2Records + 2 * glyph2class);
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
return xAdvance; return xAdvance;
} } else
} break; return 0;
default: {
// There are no other cases.
STBTT_assert(0);
break; break;
} // [DEAR IMGUI] removed ;
} }
}
break;
} // [DEAR IMGUI] removed ;
default: default:
// TODO: Implement other stuff. return 0; // Unsupported position format
break; }
} }
} }
@ -2559,8 +2618,7 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int
if (info->gpos) if (info->gpos)
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
else if (info->kern)
if (info->kern)
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
return xAdvance; return xAdvance;
@ -2621,6 +2679,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
STBTT_free(v, info->userdata); STBTT_free(v, info->userdata);
} }
STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
{
int i;
stbtt_uint8 *data = info->data;
stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
int numEntries = ttUSHORT(svg_doc_list);
stbtt_uint8 *svg_docs = svg_doc_list + 2;
for(i=0; i<numEntries; i++) {
stbtt_uint8 *svg_doc = svg_docs + (12 * i);
if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
return svg_doc;
}
return 0;
}
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
{
stbtt_uint8 *data = info->data;
stbtt_uint8 *svg_doc;
if (info->svg == 0)
return 0;
svg_doc = stbtt_FindSVGDoc(info, gl);
if (svg_doc != NULL) {
*svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
return ttULONG(svg_doc + 8);
} else {
return 0;
}
}
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
{
return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// antialiasing software rasterizer // antialiasing software rasterizer
@ -2970,6 +3067,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg
} }
} }
static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
{
STBTT_assert(top_width >= 0);
STBTT_assert(bottom_width >= 0);
return (top_width + bottom_width) / 2.0f * height;
}
static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
{
return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
}
static float stbtt__sized_triangle_area(float height, float width)
{
return height * width / 2;
}
static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
{ {
float y_bottom = y_top+1; float y_bottom = y_top+1;
@ -3024,13 +3138,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
float height; float height;
// simple case, only spans one pixel // simple case, only spans one pixel
int x = (int) x_top; int x = (int) x_top;
height = sy1 - sy0; height = (sy1 - sy0) * e->direction;
STBTT_assert(x >= 0 && x < len); STBTT_assert(x >= 0 && x < len);
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled scanline_fill[x] += height; // everything right of this pixel is filled
} else { } else {
int x,x1,x2; int x,x1,x2;
float y_crossing, step, sign, area; float y_crossing, y_final, step, sign, area;
// covers 2+ pixels // covers 2+ pixels
if (x_top > x_bottom) { if (x_top > x_bottom) {
// flip scanline vertically; signed area is the same // flip scanline vertically; signed area is the same
@ -3042,32 +3156,83 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
dx = -dx; dx = -dx;
dy = -dy; dy = -dy;
t = x0, x0 = xb, xb = t; t = x0, x0 = xb, xb = t;
// [DEAR IMGUI] Fix static analyzer warning
(void)dx; // [ImGui: fix static analyzer warning]
} }
STBTT_assert(dy >= 0);
STBTT_assert(dx >= 0);
x1 = (int) x_top; x1 = (int) x_top;
x2 = (int) x_bottom; x2 = (int) x_bottom;
// compute intersection with y axis at x1+1 // compute intersection with y axis at x1+1
y_crossing = (x1+1 - x0) * dy + y_top; y_crossing = y_top + dy * (x1+1 - x0);
// compute intersection with y axis at x2
y_final = y_top + dy * (x2 - x0);
// x1 x_top x2 x_bottom
// y_top +------|-----+------------+------------+--------|---+------------+
// | | | | | |
// | | | | | |
// sy0 | Txxxxx|............|............|............|............|
// y_crossing | *xxxxx.......|............|............|............|
// | | xxxxx..|............|............|............|
// | | /- xx*xxxx........|............|............|
// | | dy < | xxxxxx..|............|............|
// y_final | | \- | xx*xxx.........|............|
// sy1 | | | | xxxxxB...|............|
// | | | | | |
// | | | | | |
// y_bottom +------------+------------+------------+------------+------------+
//
// goal is to measure the area covered by '.' in each pixel
// if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
// @TODO: maybe test against sy1 rather than y_bottom?
if (y_crossing > y_bottom)
y_crossing = y_bottom;
sign = e->direction; sign = e->direction;
// area of the rectangle covered from y0..y_crossing
area = sign * (y_crossing-sy0);
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
step = sign * dy; // area of the rectangle covered from sy0..y_crossing
area = sign * (y_crossing-sy0);
// area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
// check if final y_crossing is blown up; no test case for this
if (y_final > y_bottom) {
int denom = (x2 - (x1+1));
y_final = y_bottom;
if (denom != 0) { // [DEAR IMGUI] Avoid div by zero (https://github.com/nothings/stb/issues/1316)
dy = (y_final - y_crossing ) / denom; // if denom=0, y_final = y_crossing, so y_final <= y_bottom
}
}
// in second pixel, area covered by line segment found in first pixel
// is always a rectangle 1 wide * the height of that line segment; this
// is exactly what the variable 'area' stores. it also gets a contribution
// from the line segment within it. the THIRD pixel will get the first
// pixel's rectangle contribution, the second pixel's rectangle contribution,
// and its own contribution. the 'own contribution' is the same in every pixel except
// the leftmost and rightmost, a trapezoid that slides down in each pixel.
// the second pixel's contribution to the third pixel will be the
// rectangle 1 wide times the height change in the second pixel, which is dy.
step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
// which multiplied by 1-pixel-width is how much pixel area changes for each step in x
// so the area advances by 'step' every time
for (x = x1+1; x < x2; ++x) { for (x = x1+1; x < x2; ++x) {
scanline[x] += area + step/2; scanline[x] += area + step/2; // area of trapezoid is 1*step/2
area += step; area += step;
} }
y_crossing += dy * (x2 - (x1+1)); STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
STBTT_assert(sy1 > y_final-0.01f);
STBTT_assert(STBTT_fabs(area) <= 1.01f); // area covered in the last pixel is the rectangle from all the pixels to the left,
// plus the trapezoid filled by the line segment in this pixel all the way to the right edge
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
// the rest of the line is filled based on the total height of the line segment in this pixel
scanline_fill[x2] += sign * (sy1-sy0); scanline_fill[x2] += sign * (sy1-sy0);
} }
} else { } else {
@ -3075,6 +3240,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
// clipping logic. since this does not match the intended use // clipping logic. since this does not match the intended use
// of this library, we use a different, very slow brute // of this library, we use a different, very slow brute
// force implementation // force implementation
// note though that this does happen some of the time because
// x_top and x_bottom can be extrapolated at the top & bottom of
// the shape and actually lie outside the bounding box
int x; int x;
for (x=0; x < len; ++x) { for (x=0; x < len; ++x) {
// cases: // cases:
@ -3989,6 +4157,7 @@ static float stbtt__oversample_shift(int oversample)
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
{ {
int i,j,k; int i,j,k;
int missing_glyph_added = 0;
k=0; k=0;
for (i=0; i < num_ranges; ++i) { for (i=0; i < num_ranges; ++i) {
@ -4000,7 +4169,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
int x0,y0,x1,y1; int x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint); int glyph = stbtt_FindGlyphIndex(info, codepoint);
if (glyph == 0 && spc->skip_missing) { if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
rects[k].w = rects[k].h = 0; rects[k].w = rects[k].h = 0;
} else { } else {
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
@ -4010,6 +4179,8 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
&x0,&y0,&x1,&y1); &x0,&y0,&x1,&y1);
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
if (glyph == 0)
missing_glyph_added = 1;
} }
++k; ++k;
} }
@ -4044,7 +4215,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
// rects array must be big enough to accommodate all characters in the given ranges // rects array must be big enough to accommodate all characters in the given ranges
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
{ {
int i,j,k, return_value = 1; int i,j,k, missing_glyph = -1, return_value = 1;
// save current values // save current values
int old_h_over = spc->h_oversample; int old_h_over = spc->h_oversample;
@ -4109,6 +4280,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
bc->yoff = (float) y0 * recip_v + sub_y; bc->yoff = (float) y0 * recip_v + sub_y;
bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
bc->yoff2 = (y0 + r->h) * recip_v + sub_y; bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
if (glyph == 0)
missing_glyph = j;
} else if (spc->skip_missing) {
return_value = 0;
} else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
} else { } else {
return_value = 0; // if any fail, report failure return_value = 0; // if any fail, report failure
} }
@ -4132,7 +4310,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
{ {
stbtt_fontinfo info; stbtt_fontinfo info;
int i,j,n, return_value; // [DEAR IMGUI] removed = 1 int i, j, n, return_value; // [DEAR IMGUI] removed = 1;
//stbrp_context *context = (stbrp_context *) spc->pack_info; //stbrp_context *context = (stbrp_context *) spc->pack_info;
stbrp_rect *rects; stbrp_rect *rects;
@ -4301,15 +4479,14 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
float y_frac; float y_frac;
int winding = 0; int winding = 0;
orig[0] = x;
//orig[1] = y; // [DEAR IMGUI] commented double assignment
// make sure y never passes through a vertex of the shape // make sure y never passes through a vertex of the shape
y_frac = (float) STBTT_fmod(y, 1.0f); y_frac = (float) STBTT_fmod(y, 1.0f);
if (y_frac < 0.01f) if (y_frac < 0.01f)
y += 0.01f; y += 0.01f;
else if (y_frac > 0.99f) else if (y_frac > 0.99f)
y -= 0.01f; y -= 0.01f;
orig[0] = x;
orig[1] = y; orig[1] = y;
// test a ray from (-infinity,y) to (x,y) // test a ray from (-infinity,y) to (x,y)
@ -4371,7 +4548,7 @@ static float stbtt__cuberoot( float x )
return (float) STBTT_pow( x,1.0f/3.0f); return (float) STBTT_pow( x,1.0f/3.0f);
} }
// x^3 + c*x^2 + b*x + a = 0 // x^3 + a*x^2 + b*x + c = 0
static int stbtt__solve_cubic(float a, float b, float c, float* r) static int stbtt__solve_cubic(float a, float b, float c, float* r)
{ {
float s = -a / 3; float s = -a / 3;
@ -4410,12 +4587,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
int w,h; int w,h;
unsigned char *data; unsigned char *data;
// if one scale is 0, use same scale for both if (scale == 0) return NULL;
if (scale_x == 0) scale_x = scale_y;
if (scale_y == 0) {
if (scale_x == 0) return NULL; // if both scales are 0, return NULL
scale_y = scale_x;
}
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
@ -4481,18 +4653,17 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
for (i=0; i < num_verts; ++i) { for (i=0; i < num_verts; ++i) {
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
// check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
if (dist2 < min_dist*min_dist) if (dist2 < min_dist*min_dist)
min_dist = (float) STBTT_sqrt(dist2); min_dist = (float) STBTT_sqrt(dist2);
if (verts[i].type == STBTT_vline) {
float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
// coarse culling against bbox // coarse culling against bbox
//if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
// sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
STBTT_assert(i != 0); STBTT_assert(i != 0);
if (dist < min_dist) { if (dist < min_dist) {
// check position along line // check position along line
@ -4519,7 +4690,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float ax = x1-x0, ay = y1-y0; float ax = x1-x0, ay = y1-y0;
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
float mx = x0 - sx, my = y0 - sy; float mx = x0 - sx, my = y0 - sy;
float res[3],px,py,t,it; float res[3] = {0.f,0.f,0.f};
float px,py,t,it,dist2;
float a_inv = precompute[i]; float a_inv = precompute[i];
if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
float a = 3*(ax*bx + ay*by); float a = 3*(ax*bx + ay*by);
@ -4546,6 +4718,10 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float d = (mx*ax+my*ay) * a_inv; float d = (mx*ax+my*ay) * a_inv;
num = stbtt__solve_cubic(b, c, d, res); num = stbtt__solve_cubic(b, c, d, res);
} }
dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
if (dist2 < min_dist*min_dist)
min_dist = (float) STBTT_sqrt(dist2);
if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
t = res[0], it = 1.0f - t; t = res[0], it = 1.0f - t;
px = it*it*x0 + 2*t*it*x1 + t*t*x2; px = it*it*x0 + 2*t*it*x1 + t*t*x2;
@ -4805,6 +4981,12 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
// FULL VERSION HISTORY // FULL VERSION HISTORY
// //
// 1.25 (2021-07-11) many fixes
// 1.24 (2020-02-05) fix warning
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
// 1.21 (2019-02-25) fix warning
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
// 1.18 (2018-01-29) add missing function // 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix // 1.17 (2017-07-23) make more arguments const; doc fix

View File

@ -159,7 +159,10 @@ if(LIBRW_PLATFORM_GL3)
) )
elseif (LIBRW_GL3_GFXLIB STREQUAL "SDL2") elseif (LIBRW_GL3_GFXLIB STREQUAL "SDL2")
if (NOT TARGET SDL2::SDL2) if (NOT TARGET SDL2::SDL2)
find_package(SDL2 REQUIRED) find_package(SDL2 CONFIG)
if (NOT TARGET SDL2::SDL2)
find_package(SDL2 MODULE REQUIRED)
endif()
endif() endif()
target_compile_definitions(librw PUBLIC LIBRW_SDL2) target_compile_definitions(librw PUBLIC LIBRW_SDL2)
target_link_libraries(librw target_link_libraries(librw

View File

@ -1513,7 +1513,10 @@ openSDL2(EngineOpenParams *openparams)
return 0; return 0;
} }
makeVideoModeList(0); glGlobals.currentDisplay = 0;
glGlobals.numDisplays = SDL_GetNumVideoDisplays();
makeVideoModeList(glGlobals.currentDisplay);
return 1; return 1;
} }
@ -1627,16 +1630,16 @@ addVideoMode(const GLFWvidmode *mode)
} }
static void static void
makeVideoModeList(void) makeVideoModeList(GLFWmonitor *monitor)
{ {
int i, num; int i, num;
const GLFWvidmode *modes; const GLFWvidmode *modes;
modes = glfwGetVideoModes(glGlobals.monitor, &num); modes = glfwGetVideoModes(monitor, &num);
rwFree(glGlobals.modes); rwFree(glGlobals.modes);
glGlobals.modes = rwNewT(DisplayMode, num+1, ID_DRIVER | MEMDUR_EVENT); glGlobals.modes = rwNewT(DisplayMode, num+1, ID_DRIVER | MEMDUR_EVENT);
glGlobals.modes[0].mode = *glfwGetVideoMode(glGlobals.monitor); glGlobals.modes[0].mode = *glfwGetVideoMode(monitor);
glGlobals.modes[0].flags = 0; glGlobals.modes[0].flags = 0;
glGlobals.numModes = 1; glGlobals.numModes = 1;
@ -1670,7 +1673,7 @@ openGLFW(EngineOpenParams *openparams)
glGlobals.monitor = glfwGetMonitors(&glGlobals.numMonitors)[0]; glGlobals.monitor = glfwGetMonitors(&glGlobals.numMonitors)[0];
makeVideoModeList(); makeVideoModeList(glGlobals.monitor);
return 1; return 1;
} }
@ -1940,7 +1943,27 @@ deviceSystemSDL2(DeviceReq req, void *arg, int32 n)
case DEVICEFINALIZE: case DEVICEFINALIZE:
return finalizeOpenGL(); return finalizeOpenGL();
// TODO: implement subsystems
case DEVICEGETNUMSUBSYSTEMS:
return glGlobals.numDisplays;
case DEVICEGETCURRENTSUBSYSTEM:
return glGlobals.currentDisplay;
case DEVICESETSUBSYSTEM:
if (n >= SDL_GetNumVideoDisplays())
return 0;
glGlobals.currentDisplay = n;
return 1;
case DEVICEGETSUBSSYSTEMINFO: {
const char *display_name = SDL_GetDisplayName(n);
if (display_name == nil)
return 0;
strncpy(((SubSystemInfo*)arg)->name, display_name, sizeof(SubSystemInfo::name));
return 1;
}
case DEVICEGETNUMVIDEOMODES: case DEVICEGETNUMVIDEOMODES:
return glGlobals.numModes; return glGlobals.numModes;

View File

@ -39,6 +39,9 @@ struct GlGlobals
SDL_Window **pWindow; SDL_Window **pWindow;
SDL_Window *window; SDL_Window *window;
SDL_GLContext glcontext; SDL_GLContext glcontext;
int numDisplays;
int currentDisplay;
#else #else
GLFWwindow **pWindow; GLFWwindow **pWindow;
GLFWwindow *window; GLFWwindow *window;

View File

@ -7,6 +7,10 @@ target_link_libraries(dumprwtree
librw::librw librw::librw
) )
if(LIBRW_GL3_GFXLIB STREQUAL "SDL2")
target_compile_definitions(dumprwtree PRIVATE SDL_MAIN_HANDLED)
endif()
if(LIBRW_INSTALL) if(LIBRW_INSTALL)
install(TARGETS dumprwtree install(TARGETS dumprwtree
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"

View File

@ -7,10 +7,14 @@ target_link_libraries(ska2anm
librw::librw librw::librw
) )
librw_platform_target(ska2anm INSTALL) if(LIBRW_GL3_GFXLIB STREQUAL "SDL2")
target_compile_definitions(ska2anm PRIVATE SDL_MAIN_HANDLED)
endif()
if(LIBRW_INSTALL) if(LIBRW_INSTALL)
install(TARGETS ska2anm install(TARGETS ska2anm
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
) )
endif() endif()
librw_platform_target(ska2anm INSTALL)