diff --git a/.gradle/9.4.1/executionHistory/executionHistory.bin b/.gradle/9.4.1/executionHistory/executionHistory.bin index 79d55ab..9584f4d 100644 Binary files a/.gradle/9.4.1/executionHistory/executionHistory.bin and b/.gradle/9.4.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/9.4.1/executionHistory/executionHistory.lock b/.gradle/9.4.1/executionHistory/executionHistory.lock index 93194a1..a87df25 100644 Binary files a/.gradle/9.4.1/executionHistory/executionHistory.lock and b/.gradle/9.4.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/9.4.1/fileHashes/fileHashes.bin b/.gradle/9.4.1/fileHashes/fileHashes.bin index 6191118..3706882 100644 Binary files a/.gradle/9.4.1/fileHashes/fileHashes.bin and b/.gradle/9.4.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/9.4.1/fileHashes/fileHashes.lock b/.gradle/9.4.1/fileHashes/fileHashes.lock index ab02c28..2ac9f60 100644 Binary files a/.gradle/9.4.1/fileHashes/fileHashes.lock and b/.gradle/9.4.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/9.4.1/fileHashes/resourceHashesCache.bin b/.gradle/9.4.1/fileHashes/resourceHashesCache.bin index 29baa19..493b878 100644 Binary files a/.gradle/9.4.1/fileHashes/resourceHashesCache.bin and b/.gradle/9.4.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index c781d4b..1db847d 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T03-54-59-0383.json b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T06-57-38-0532.json similarity index 100% rename from app/.cxx/Debug/j1t3m4l4/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T03-54-59-0383.json rename to app/.cxx/Debug/j1t3m4l4/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T06-57-38-0532.json diff --git a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_deps b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_deps index 07bbd25..6632527 100644 Binary files a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_deps and b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_deps differ diff --git a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_log b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_log index 41e9782..2ab183f 100644 --- a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_log +++ b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/.ninja_log @@ -1,20 +1,20 @@ # ninja log v5 -0 92 8029396993585839 build.ninja 2f5a2ae5718e4ec9 -14 762 8029185021516776 CMakeFiles/kcompressor.dir/native_compressor.cpp.o f1cdbf4574e80c54 -1140 1359 8029185026652331 D:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/arm64-v8a/libkcompressor.so 2ed2a8e4fb32e2f1 +4 812 8029480314360756 CMakeFiles/kcompressor.dir/native_compressor.cpp.o f1cdbf4574e80c54 +0 97 8029506585127615 build.ninja 2f5a2ae5718e4ec9 +1141 1378 8029480319061115 D:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/arm64-v8a/libkcompressor.so 106ffbe4417f09dd +0 8 0 clean 267b28daf0e986 +8 740 8029480313668964 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 51cecdb4bb34bbf4 +13 1140 8029480317633298 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 9626d49d842157ab +11 1096 8029480317229392 CMakeFiles/kcompressor.dir/video_compressor.cpp.o a7433b92b28b1b44 +8 920 8029506594888005 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 51cecdb4bb34bbf4 +4 981 8029506595545332 CMakeFiles/kcompressor.dir/native_compressor.cpp.o f1cdbf4574e80c54 +10 1256 8029506598268452 CMakeFiles/kcompressor.dir/video_compressor.cpp.o a7433b92b28b1b44 +13 1310 8029506598761157 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 9626d49d842157ab +1310 1559 8029506600257667 D:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/arm64-v8a/libkcompressor.so 106ffbe4417f09dd +0 10 0 clean 267b28daf0e986 +9 824 8029513444895799 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 51cecdb4bb34bbf4 +6 898 8029513445625201 CMakeFiles/kcompressor.dir/native_compressor.cpp.o f1cdbf4574e80c54 +17 1202 8029513448628426 CMakeFiles/kcompressor.dir/video_compressor.cpp.o a7433b92b28b1b44 +13 1241 8029513448985205 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 9626d49d842157ab +1241 1465 8029513450464697 D:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/arm64-v8a/libkcompressor.so 106ffbe4417f09dd 0 11 0 clean 267b28daf0e986 -5 739 8029185021291292 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 51cecdb4bb34bbf4 -8 1086 8029185024740912 CMakeFiles/kcompressor.dir/video_compressor.cpp.o a7433b92b28b1b44 -11 1140 8029185025251562 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 9626d49d842157ab -8 1153 8029397006271551 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 51cecdb4bb34bbf4 -5 1168 8029397006428182 CMakeFiles/kcompressor.dir/native_compressor.cpp.o f1cdbf4574e80c54 -10 1483 8029397009545197 CMakeFiles/kcompressor.dir/video_compressor.cpp.o a7433b92b28b1b44 -13 1543 8029397010132834 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 9626d49d842157ab -1543 2447 8029397018248978 D:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/arm64-v8a/libkcompressor.so 106ffbe4417f09dd -0 10 0 clean 267b28daf0e986 -13 1134 8029402129560801 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 51cecdb4bb34bbf4 -8 1157 8029402129804881 CMakeFiles/kcompressor.dir/native_compressor.cpp.o f1cdbf4574e80c54 -21 1514 8029402133356799 CMakeFiles/kcompressor.dir/video_compressor.cpp.o a7433b92b28b1b44 -17 1561 8029402133742631 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 9626d49d842157ab -1561 1792 8029402135289547 D:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/arm64-v8a/libkcompressor.so 106ffbe4417f09dd -0 10 0 clean 267b28daf0e986 diff --git a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/configure_fingerprint.bin b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/configure_fingerprint.bin index 99613c6..4618dd7 100644 --- a/app/.cxx/Debug/j1t3m4l4/arm64-v8a/configure_fingerprint.bin +++ b/app/.cxx/Debug/j1t3m4l4/arm64-v8a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Log[ Y WD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  3  ڇ3X +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  3  3X V -TD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\android_gradle_build.json  3 ܇3] +TD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\android_gradle_build.json  3 3] [ -YD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\android_gradle_build_mini.json  3 3J +YD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\android_gradle_build_mini.json  3 3J H -FD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\build.ninja  3 3N +FD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\build.ninja  3 3N L -JD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\build.ninja.txt  3S +JD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\build.ninja.txt  3S Q -OD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\build_file_index.txt  3 8 3T +OD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\build_file_index.txt  3 8 3T R -PD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\compile_commands.json  3' 3X +PD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\compile_commands.json  3' 3X V -TD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\compile_commands.json.bin  3  3^ +TD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\compile_commands.json.bin  3  3^ \ -ZD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\metadata_generation_command.txt  3 +ZD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\metadata_generation_command.txt  3  3Q O -MD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\prefab_config.json  3  ( 3V +MD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\prefab_config.json  3  ( 3V T -RD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\symbol_folder_index.txt  3  Q 3< +RD:\MyProject\kcompressor\app\.cxx\Debug\j1t3m4l4\arm64-v8a\symbol_folder_index.txt  3  Q 3< : -8D:\MyProject\kcompressor\app\src\main\cpp\CMakeLists.txt  3  3 \ No newline at end of file +8D:\MyProject\kcompressor\app\src\main\cpp\CMakeLists.txt  3  3 \ No newline at end of file diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/cmakeFiles-v1-29f5731a000e123c37c8.json b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/cmakeFiles-v1-29f5731a000e123c37c8.json new file mode 100644 index 0000000..92729cf --- /dev/null +++ b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/cmakeFiles-v1-29f5731a000e123c37c8.json @@ -0,0 +1,188 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86", + "source" : "D:/MyProject/kcompressor/app/src/main/cpp" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/cmakeFiles-v1-816317ebe17bd015b004.json b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/cmakeFiles-v1-816317ebe17bd015b004.json deleted file mode 100644 index e079c24..0000000 --- a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/cmakeFiles-v1-816317ebe17bd015b004.json +++ /dev/null @@ -1,803 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "D:/MyProject/kcompressor/app/.cxx/Debug/j1t3m4l4/x86", - "source" : "D:/MyProject/kcompressor/app/src/main/cpp" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/codemodel-v2-1c2dfbc938f6e8d2bdc4.json b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/codemodel-v2-fec8e92bb9819ccfa7f0.json similarity index 93% rename from app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/codemodel-v2-1c2dfbc938f6e8d2bdc4.json rename to app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/codemodel-v2-fec8e92bb9819ccfa7f0.json index f3e3a36..1a22342 100644 --- a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/codemodel-v2-1c2dfbc938f6e8d2bdc4.json +++ b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/codemodel-v2-fec8e92bb9819ccfa7f0.json @@ -39,7 +39,7 @@ { "directoryIndex" : 0, "id" : "kcompressor::@6890427a1f51a3e7e1df", - "jsonFile" : "target-kcompressor-Debug-ae80138bec7f082a7437.json", + "jsonFile" : "target-kcompressor-Debug-1aaac36e3445681fcf73.json", "name" : "kcompressor", "projectIndex" : 0 } diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/index-2026-06-11T22-03-38-0486.json b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0192.json similarity index 84% rename from app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/index-2026-06-11T22-03-38-0486.json rename to app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0192.json index 17bcc53..1fcf454 100644 --- a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/index-2026-06-11T22-03-38-0486.json +++ b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0192.json @@ -26,7 +26,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-1c2dfbc938f6e8d2bdc4.json", + "jsonFile" : "codemodel-v2-fec8e92bb9819ccfa7f0.json", "kind" : "codemodel", "version" : { @@ -44,7 +44,7 @@ } }, { - "jsonFile" : "cmakeFiles-v1-816317ebe17bd015b004.json", + "jsonFile" : "cmakeFiles-v1-29f5731a000e123c37c8.json", "kind" : "cmakeFiles", "version" : { @@ -69,7 +69,7 @@ }, "cmakeFiles-v1" : { - "jsonFile" : "cmakeFiles-v1-816317ebe17bd015b004.json", + "jsonFile" : "cmakeFiles-v1-29f5731a000e123c37c8.json", "kind" : "cmakeFiles", "version" : { @@ -79,7 +79,7 @@ }, "codemodel-v2" : { - "jsonFile" : "codemodel-v2-1c2dfbc938f6e8d2bdc4.json", + "jsonFile" : "codemodel-v2-fec8e92bb9819ccfa7f0.json", "kind" : "codemodel", "version" : { diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/target-kcompressor-Debug-ae80138bec7f082a7437.json b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/target-kcompressor-Debug-1aaac36e3445681fcf73.json similarity index 98% rename from app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/target-kcompressor-Debug-ae80138bec7f082a7437.json rename to app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/target-kcompressor-Debug-1aaac36e3445681fcf73.json index 171bb6a..94f3d9e 100644 --- a/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/target-kcompressor-Debug-ae80138bec7f082a7437.json +++ b/app/.cxx/Debug/j1t3m4l4/x86/.cmake/api/v1/reply/target-kcompressor-Debug-1aaac36e3445681fcf73.json @@ -227,6 +227,11 @@ "fragment" : "-Wl,--end-group", "role" : "libraries" }, + { + "backtrace" : 2, + "fragment" : "-lmediandk", + "role" : "libraries" + }, { "backtrace" : 2, "fragment" : "-landroid", diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.ninja_deps b/app/.cxx/Debug/j1t3m4l4/x86/.ninja_deps new file mode 100644 index 0000000..e5675ec Binary files /dev/null and b/app/.cxx/Debug/j1t3m4l4/x86/.ninja_deps differ diff --git a/app/.cxx/Debug/j1t3m4l4/x86/.ninja_log b/app/.cxx/Debug/j1t3m4l4/x86/.ninja_log index 48e52f2..ce032a2 100644 --- a/app/.cxx/Debug/j1t3m4l4/x86/.ninja_log +++ b/app/.cxx/Debug/j1t3m4l4/x86/.ninja_log @@ -1,3 +1,7 @@ # ninja log v5 +0 11 0 clean 267b28daf0e986 +2 143 8029506551739850 build.ninja f83080019da48f8e +0 91 8029506551739850 build.ninja f83080019da48f8e +0 7 0 clean 267b28daf0e986 0 8 0 clean 267b28daf0e986 0 9 0 clean 267b28daf0e986 diff --git a/app/.cxx/Debug/j1t3m4l4/x86/build.ninja b/app/.cxx/Debug/j1t3m4l4/x86/build.ninja index 2392e72..cf84cde 100644 --- a/app/.cxx/Debug/j1t3m4l4/x86/build.ninja +++ b/app/.cxx/Debug/j1t3m4l4/x86/build.ninja @@ -56,8 +56,6 @@ build CMakeFiles/kcompressor.dir/native_compressor.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\Debug\j1t3m4l4\obj\x86\libkcompressor.pdb build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompressor_Debug D$:/MyProject/kcompressor/app/src/main/cpp/compressor_common.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -66,8 +64,6 @@ build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\Debug\j1t3m4l4\obj\x86\libkcompressor.pdb build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompressor_Debug D$:/MyProject/kcompressor/app/src/main/cpp/video_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -76,8 +72,6 @@ build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\Debug\j1t3m4l4\obj\x86\libkcompressor.pdb build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompressor_Debug D$:/MyProject/kcompressor/app/src/main/cpp/image_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -86,8 +80,6 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\Debug\j1t3m4l4\obj\x86\libkcompressor.pdb # ============================================================================= @@ -100,15 +92,14 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress build D$:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t3m4l4/obj/x86/libkcompressor.so: CXX_SHARED_LIBRARY_LINKER__kcompressor_Debug CMakeFiles/kcompressor.dir/native_compressor.cpp.o CMakeFiles/kcompressor.dir/compressor_common.cpp.o CMakeFiles/kcompressor.dir/video_compressor.cpp.o CMakeFiles/kcompressor.dir/image_compressor.cpp.o | D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx264.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx265.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libturbojpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libjpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libwebp.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libsharpyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libavif.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libaom.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libimagequant.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/liboxipng_ffi.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libkimage_png.a LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++17 -fexceptions -frtti -fno-limit-debug-info LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments - LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libkimage_png.a -Wl,--end-group -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm + LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libkimage_png.a -Wl,--end-group -lmediandk -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm OBJECT_DIR = CMakeFiles\kcompressor.dir POST_BUILD = cd . PRE_LINK = cd . SONAME = libkcompressor.so SONAME_FLAG = -Wl,-soname, - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ TARGET_FILE = D:\MyProject\kcompressor\app\build\intermediates\cxx\Debug\j1t3m4l4\obj\x86\libkcompressor.so - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\Debug\j1t3m4l4\obj\x86\libkcompressor.pdb + TARGET_PDB = kcompressor.so.dbg ############################################# @@ -157,14 +148,14 @@ build all: phony D$:/MyProject/kcompressor/app/build/intermediates/cxx/Debug/j1t ############################################# # Re-run CMake if any of its inputs changed. -build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt +build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt pool = console ############################################# # A missing CMake input file is not an error. -build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony +build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony ############################################# diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-3abc5f63397bb35955a6.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-3abc5f63397bb35955a6.json new file mode 100644 index 0000000..21fb599 --- /dev/null +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-3abc5f63397bb35955a6.json @@ -0,0 +1,188 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a", + "source" : "D:/MyProject/kcompressor/app/src/main/cpp" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-ff60db6e57d229ebd4fb.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-ff60db6e57d229ebd4fb.json deleted file mode 100644 index c37bef4..0000000 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-ff60db6e57d229ebd4fb.json +++ /dev/null @@ -1,803 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a", - "source" : "D:/MyProject/kcompressor/app/src/main/cpp" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ca44f5329f21eeb68a38.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-a509508c860c257628de.json similarity index 92% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ca44f5329f21eeb68a38.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-a509508c860c257628de.json index 15c9d00..6d11d73 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ca44f5329f21eeb68a38.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-a509508c860c257628de.json @@ -39,7 +39,7 @@ { "directoryIndex" : 0, "id" : "kcompressor::@6890427a1f51a3e7e1df", - "jsonFile" : "target-kcompressor-RelWithDebInfo-745c599d677a0a62bc26.json", + "jsonFile" : "target-kcompressor-RelWithDebInfo-629175f078d00ae34e12.json", "name" : "kcompressor", "projectIndex" : 0 } diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/index-2026-06-11T22-06-29-0067.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0447.json similarity index 84% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/index-2026-06-11T22-06-29-0067.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0447.json index cfc5aaa..3f8073c 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/index-2026-06-11T22-06-29-0067.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0447.json @@ -26,7 +26,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-ca44f5329f21eeb68a38.json", + "jsonFile" : "codemodel-v2-a509508c860c257628de.json", "kind" : "codemodel", "version" : { @@ -44,7 +44,7 @@ } }, { - "jsonFile" : "cmakeFiles-v1-ff60db6e57d229ebd4fb.json", + "jsonFile" : "cmakeFiles-v1-3abc5f63397bb35955a6.json", "kind" : "cmakeFiles", "version" : { @@ -69,7 +69,7 @@ }, "cmakeFiles-v1" : { - "jsonFile" : "cmakeFiles-v1-ff60db6e57d229ebd4fb.json", + "jsonFile" : "cmakeFiles-v1-3abc5f63397bb35955a6.json", "kind" : "cmakeFiles", "version" : { @@ -79,7 +79,7 @@ }, "codemodel-v2" : { - "jsonFile" : "codemodel-v2-ca44f5329f21eeb68a38.json", + "jsonFile" : "codemodel-v2-a509508c860c257628de.json", "kind" : "codemodel", "version" : { diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-745c599d677a0a62bc26.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-629175f078d00ae34e12.json similarity index 98% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-745c599d677a0a62bc26.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-629175f078d00ae34e12.json index faeebc8..b903326 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-745c599d677a0a62bc26.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-629175f078d00ae34e12.json @@ -227,6 +227,11 @@ "fragment" : "-Wl,--end-group", "role" : "libraries" }, + { + "backtrace" : 2, + "fragment" : "-lmediandk", + "role" : "libraries" + }, { "backtrace" : 2, "fragment" : "-landroid", diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.ninja_log b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.ninja_log index fb0bbc7..840e7ec 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.ninja_log +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/.ninja_log @@ -1,8 +1,12 @@ # ninja log v5 0 794 8029187898973068 CMakeFiles/kcompressor.dir/compressor_common.cpp.o adb2af10dbb0ffbb +0 95 8029506554287663 build.ninja 4ea1f7cd834922f1 3 814 8029187899145234 CMakeFiles/kcompressor.dir/native_compressor.cpp.o fe03857812d5987e 5 1362 8029187904608351 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 966f53d8dadbca3b 8 1427 8029187905203701 CMakeFiles/kcompressor.dir/video_compressor.cpp.o d7b1b2f4d613b4df 1428 1667 8029187906763470 D:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/arm64-v8a/libkcompressor.so a8059da3bd0eeb96 -0 9 0 clean 267b28daf0e986 -0 9 0 clean 267b28daf0e986 +0 8 0 clean 267b28daf0e986 +1 92 8029506554287663 build.ninja 4ea1f7cd834922f1 +0 7 0 clean 267b28daf0e986 +0 12 0 clean 267b28daf0e986 +0 8 0 clean 267b28daf0e986 diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/build.ninja b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/build.ninja index f54ed56..354ce56 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/build.ninja +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/arm64-v8a/build.ninja @@ -56,8 +56,6 @@ build CMakeFiles/kcompressor.dir/native_compressor.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\arm64-v8a\libkcompressor.pdb build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/compressor_common.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -66,8 +64,6 @@ build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\arm64-v8a\libkcompressor.pdb build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/video_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -76,8 +72,6 @@ build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\arm64-v8a\libkcompressor.pdb build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/image_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -86,8 +80,6 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\arm64-v8a\libkcompressor.pdb # ============================================================================= @@ -100,15 +92,14 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress build D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/arm64-v8a/libkcompressor.so: CXX_SHARED_LIBRARY_LINKER__kcompressor_RelWithDebInfo CMakeFiles/kcompressor.dir/native_compressor.cpp.o CMakeFiles/kcompressor.dir/compressor_common.cpp.o CMakeFiles/kcompressor.dir/video_compressor.cpp.o CMakeFiles/kcompressor.dir/image_compressor.cpp.o | D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libx264.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libx265.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libturbojpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libjpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libwebp.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libsharpyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libavif.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libaom.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libimagequant.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/liboxipng_ffi.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libkimage_png.a LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++17 -fexceptions -frtti -O2 -g -DNDEBUG LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,--gc-sections - LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libkimage_png.a -Wl,--end-group -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm + LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/arm64-v8a/lib/libkimage_png.a -Wl,--end-group -lmediandk -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm OBJECT_DIR = CMakeFiles\kcompressor.dir POST_BUILD = cd . PRE_LINK = cd . SONAME = libkcompressor.so SONAME_FLAG = -Wl,-soname, - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ TARGET_FILE = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\arm64-v8a\libkcompressor.so - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\arm64-v8a\libkcompressor.pdb + TARGET_PDB = kcompressor.so.dbg ############################################# @@ -157,14 +148,14 @@ build all: phony D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDe ############################################# # Re-run CMake if any of its inputs changed. -build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt +build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt pool = console ############################################# # A missing CMake input file is not an error. -build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony +build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony ############################################# diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-1e77ed3892865ae67a2a.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-1e77ed3892865ae67a2a.json new file mode 100644 index 0000000..4b32975 --- /dev/null +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-1e77ed3892865ae67a2a.json @@ -0,0 +1,188 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a", + "source" : "D:/MyProject/kcompressor/app/src/main/cpp" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-864ecaeb9d56f94c7529.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-864ecaeb9d56f94c7529.json deleted file mode 100644 index 769594a..0000000 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-864ecaeb9d56f94c7529.json +++ /dev/null @@ -1,803 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a", - "source" : "D:/MyProject/kcompressor/app/src/main/cpp" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-5e9f9d1615c87e7f8cde.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-dcc619b9c8e7323ecd00.json similarity index 92% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-5e9f9d1615c87e7f8cde.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-dcc619b9c8e7323ecd00.json index 8b046ee..b46af6a 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-5e9f9d1615c87e7f8cde.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-dcc619b9c8e7323ecd00.json @@ -39,7 +39,7 @@ { "directoryIndex" : 0, "id" : "kcompressor::@6890427a1f51a3e7e1df", - "jsonFile" : "target-kcompressor-RelWithDebInfo-4dc1e40339f74e2db246.json", + "jsonFile" : "target-kcompressor-RelWithDebInfo-25940feaa70a370999db.json", "name" : "kcompressor", "projectIndex" : 0 } diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/index-2026-06-11T22-06-31-0947.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0322.json similarity index 84% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/index-2026-06-11T22-06-31-0947.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0322.json index 46d1437..6798eda 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/index-2026-06-11T22-06-31-0947.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0322.json @@ -26,7 +26,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-5e9f9d1615c87e7f8cde.json", + "jsonFile" : "codemodel-v2-dcc619b9c8e7323ecd00.json", "kind" : "codemodel", "version" : { @@ -44,7 +44,7 @@ } }, { - "jsonFile" : "cmakeFiles-v1-864ecaeb9d56f94c7529.json", + "jsonFile" : "cmakeFiles-v1-1e77ed3892865ae67a2a.json", "kind" : "cmakeFiles", "version" : { @@ -69,7 +69,7 @@ }, "cmakeFiles-v1" : { - "jsonFile" : "cmakeFiles-v1-864ecaeb9d56f94c7529.json", + "jsonFile" : "cmakeFiles-v1-1e77ed3892865ae67a2a.json", "kind" : "cmakeFiles", "version" : { @@ -79,7 +79,7 @@ }, "codemodel-v2" : { - "jsonFile" : "codemodel-v2-5e9f9d1615c87e7f8cde.json", + "jsonFile" : "codemodel-v2-dcc619b9c8e7323ecd00.json", "kind" : "codemodel", "version" : { diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-4dc1e40339f74e2db246.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-25940feaa70a370999db.json similarity index 98% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-4dc1e40339f74e2db246.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-25940feaa70a370999db.json index 0c4a3df..836616b 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-4dc1e40339f74e2db246.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-25940feaa70a370999db.json @@ -227,6 +227,11 @@ "fragment" : "-Wl,--end-group", "role" : "libraries" }, + { + "backtrace" : 2, + "fragment" : "-lmediandk", + "role" : "libraries" + }, { "backtrace" : 2, "fragment" : "-landroid", diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.ninja_log b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.ninja_log index ccbca26..216b100 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.ninja_log +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/.ninja_log @@ -1,8 +1,12 @@ # ninja log v5 0 787 8029187927760538 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 6a18ebe4bf23ff4c +1451 1700 8029187936161958 D:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/armeabi-v7a/libkcompressor.so d83368780ff05daf +1 92 8029506553058322 build.ninja de0149c609cfe238 4 830 8029187928180710 CMakeFiles/kcompressor.dir/native_compressor.cpp.o 2561d13e2ec28901 6 1371 8029187933562682 CMakeFiles/kcompressor.dir/image_compressor.cpp.o c99d1a9dc80d375b 9 1450 8029187934303847 CMakeFiles/kcompressor.dir/video_compressor.cpp.o 32681f6efee839b1 -1451 1700 8029187936161958 D:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/armeabi-v7a/libkcompressor.so d83368780ff05daf -0 9 0 clean 267b28daf0e986 0 11 0 clean 267b28daf0e986 +1 93 8029506553058322 build.ninja de0149c609cfe238 +0 7 0 clean 267b28daf0e986 +0 10 0 clean 267b28daf0e986 +0 9 0 clean 267b28daf0e986 diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/build.ninja b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/build.ninja index 61b3588..e0cb5d1 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/build.ninja +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/armeabi-v7a/build.ninja @@ -56,8 +56,6 @@ build CMakeFiles/kcompressor.dir/native_compressor.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\armeabi-v7a\libkcompressor.pdb build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/compressor_common.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -66,8 +64,6 @@ build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\armeabi-v7a\libkcompressor.pdb build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/video_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -76,8 +72,6 @@ build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\armeabi-v7a\libkcompressor.pdb build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/image_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -86,8 +80,6 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\armeabi-v7a\libkcompressor.pdb # ============================================================================= @@ -100,15 +92,14 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress build D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/armeabi-v7a/libkcompressor.so: CXX_SHARED_LIBRARY_LINKER__kcompressor_RelWithDebInfo CMakeFiles/kcompressor.dir/native_compressor.cpp.o CMakeFiles/kcompressor.dir/compressor_common.cpp.o CMakeFiles/kcompressor.dir/video_compressor.cpp.o CMakeFiles/kcompressor.dir/image_compressor.cpp.o | D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libx264.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libx265.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libturbojpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libjpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libwebp.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libsharpyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libavif.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libaom.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libimagequant.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/liboxipng_ffi.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libkimage_png.a LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -std=c++17 -fexceptions -frtti -O2 -g -DNDEBUG LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,--gc-sections - LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libkimage_png.a -Wl,--end-group -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm + LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/armeabi-v7a/lib/libkimage_png.a -Wl,--end-group -lmediandk -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm OBJECT_DIR = CMakeFiles\kcompressor.dir POST_BUILD = cd . PRE_LINK = cd . SONAME = libkcompressor.so SONAME_FLAG = -Wl,-soname, - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ TARGET_FILE = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\armeabi-v7a\libkcompressor.so - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\armeabi-v7a\libkcompressor.pdb + TARGET_PDB = kcompressor.so.dbg ############################################# @@ -157,14 +148,14 @@ build all: phony D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDe ############################################# # Re-run CMake if any of its inputs changed. -build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt +build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt pool = console ############################################# # A missing CMake input file is not an error. -build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony +build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony ############################################# diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/codemodel-v2-cc2b53ce3a30785fbd5e.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/codemodel-v2-0d230ca2ec7fffcc65d0.json similarity index 91% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/codemodel-v2-cc2b53ce3a30785fbd5e.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/codemodel-v2-0d230ca2ec7fffcc65d0.json index f2503b4..4a4efa0 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/codemodel-v2-cc2b53ce3a30785fbd5e.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/codemodel-v2-0d230ca2ec7fffcc65d0.json @@ -39,7 +39,7 @@ { "directoryIndex" : 0, "id" : "kcompressor::@6890427a1f51a3e7e1df", - "jsonFile" : "target-kcompressor-RelWithDebInfo-fb91a9f13fd2d7dbcec7.json", + "jsonFile" : "target-kcompressor-RelWithDebInfo-1b896933e8907deccf69.json", "name" : "kcompressor", "projectIndex" : 0 } diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/index-2026-06-11T22-06-34-0078.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0572.json similarity index 92% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/index-2026-06-11T22-06-34-0078.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0572.json index 415319d..1373596 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/index-2026-06-11T22-06-34-0078.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0572.json @@ -26,7 +26,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-cc2b53ce3a30785fbd5e.json", + "jsonFile" : "codemodel-v2-0d230ca2ec7fffcc65d0.json", "kind" : "codemodel", "version" : { @@ -79,7 +79,7 @@ }, "codemodel-v2" : { - "jsonFile" : "codemodel-v2-cc2b53ce3a30785fbd5e.json", + "jsonFile" : "codemodel-v2-0d230ca2ec7fffcc65d0.json", "kind" : "codemodel", "version" : { diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-fb91a9f13fd2d7dbcec7.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-1b896933e8907deccf69.json similarity index 98% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-fb91a9f13fd2d7dbcec7.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-1b896933e8907deccf69.json index cbb909f..1fbaba9 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-fb91a9f13fd2d7dbcec7.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-1b896933e8907deccf69.json @@ -227,6 +227,11 @@ "fragment" : "-Wl,--end-group", "role" : "libraries" }, + { + "backtrace" : 2, + "fragment" : "-lmediandk", + "role" : "libraries" + }, { "backtrace" : 2, "fragment" : "-landroid", diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.ninja_log b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.ninja_log index b630e6e..526f736 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.ninja_log +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/.ninja_log @@ -1,10 +1,12 @@ # ninja log v5 -0 9 0 clean 267b28daf0e986 -1 100 8029187940586389 build.ninja af12574c3879f389 -3 776 8029187948911413 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 39bdd443ba7e458d +0 8 0 clean 267b28daf0e986 +0 100 8029506555540742 build.ninja af12574c3879f389 0 824 8029187949395675 CMakeFiles/kcompressor.dir/native_compressor.cpp.o c4401d2af9681fa8 +3 776 8029187948911413 CMakeFiles/kcompressor.dir/compressor_common.cpp.o 39bdd443ba7e458d 6 1412 8029187955245026 CMakeFiles/kcompressor.dir/image_compressor.cpp.o 70fefa06449145a1 8 1523 8029187956312024 CMakeFiles/kcompressor.dir/video_compressor.cpp.o 627e3e3b8c70a589 1523 1718 8029187957662419 D:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/x86/libkcompressor.so 8a9e3764c4fde8af +0 92 8029506555540742 build.ninja af12574c3879f389 +0 8 0 clean 267b28daf0e986 +0 9 0 clean 267b28daf0e986 0 9 0 clean 267b28daf0e986 -0 7 0 clean 267b28daf0e986 diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/build.ninja b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/build.ninja index 4ef1ad3..4f0c5d2 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/build.ninja +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86/build.ninja @@ -92,7 +92,7 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress build D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/x86/libkcompressor.so: CXX_SHARED_LIBRARY_LINKER__kcompressor_RelWithDebInfo CMakeFiles/kcompressor.dir/native_compressor.cpp.o CMakeFiles/kcompressor.dir/compressor_common.cpp.o CMakeFiles/kcompressor.dir/video_compressor.cpp.o CMakeFiles/kcompressor.dir/image_compressor.cpp.o | D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx264.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx265.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libturbojpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libjpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libwebp.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libsharpyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libavif.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libaom.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libimagequant.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/liboxipng_ffi.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libkimage_png.a LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++17 -fexceptions -frtti -O2 -g -DNDEBUG LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,--gc-sections - LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libkimage_png.a -Wl,--end-group -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm + LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86/lib/libkimage_png.a -Wl,--end-group -lmediandk -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm OBJECT_DIR = CMakeFiles\kcompressor.dir POST_BUILD = cd . PRE_LINK = cd . diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-2473dbf68cffdc6fc751.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-2473dbf68cffdc6fc751.json deleted file mode 100644 index f71eee4..0000000 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-2473dbf68cffdc6fc751.json +++ /dev/null @@ -1,803 +0,0 @@ -{ - "inputs" : - [ - { - "path" : "CMakeLists.txt" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" - }, - { - "isExternal" : true, - "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" - }, - { - "isCMake" : true, - "isExternal" : true, - "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in" - }, - { - "isGenerated" : true, - "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" - } - ], - "kind" : "cmakeFiles", - "paths" : - { - "build" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64", - "source" : "D:/MyProject/kcompressor/app/src/main/cpp" - }, - "version" : - { - "major" : 1, - "minor" : 0 - } -} diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-b45bcbff36384d7096d0.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-b45bcbff36384d7096d0.json new file mode 100644 index 0000000..8186cef --- /dev/null +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-b45bcbff36384d7096d0.json @@ -0,0 +1,188 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake" + }, + { + "isGenerated" : true, + "path" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "D:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "D:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "D:/MyProject/kcompressor/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64", + "source" : "D:/MyProject/kcompressor/app/src/main/cpp" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/codemodel-v2-2aa65859c809d225bace.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/codemodel-v2-7d8f93174a7b687bb5f3.json similarity index 91% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/codemodel-v2-2aa65859c809d225bace.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/codemodel-v2-7d8f93174a7b687bb5f3.json index 232327f..2845146 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/codemodel-v2-2aa65859c809d225bace.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/codemodel-v2-7d8f93174a7b687bb5f3.json @@ -39,7 +39,7 @@ { "directoryIndex" : 0, "id" : "kcompressor::@6890427a1f51a3e7e1df", - "jsonFile" : "target-kcompressor-RelWithDebInfo-f612c8e8deb350eb4aaa.json", + "jsonFile" : "target-kcompressor-RelWithDebInfo-755384221a37a352fad1.json", "name" : "kcompressor", "projectIndex" : 0 } diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/index-2026-06-11T22-06-36-0890.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0696.json similarity index 84% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/index-2026-06-11T22-06-36-0890.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0696.json index 7b9e290..93c48e2 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/index-2026-06-11T22-06-36-0890.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/index-2026-06-12T06-57-35-0696.json @@ -26,7 +26,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-2aa65859c809d225bace.json", + "jsonFile" : "codemodel-v2-7d8f93174a7b687bb5f3.json", "kind" : "codemodel", "version" : { @@ -44,7 +44,7 @@ } }, { - "jsonFile" : "cmakeFiles-v1-2473dbf68cffdc6fc751.json", + "jsonFile" : "cmakeFiles-v1-b45bcbff36384d7096d0.json", "kind" : "cmakeFiles", "version" : { @@ -69,7 +69,7 @@ }, "cmakeFiles-v1" : { - "jsonFile" : "cmakeFiles-v1-2473dbf68cffdc6fc751.json", + "jsonFile" : "cmakeFiles-v1-b45bcbff36384d7096d0.json", "kind" : "cmakeFiles", "version" : { @@ -79,7 +79,7 @@ }, "codemodel-v2" : { - "jsonFile" : "codemodel-v2-2aa65859c809d225bace.json", + "jsonFile" : "codemodel-v2-7d8f93174a7b687bb5f3.json", "kind" : "codemodel", "version" : { diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-f612c8e8deb350eb4aaa.json b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-755384221a37a352fad1.json similarity index 98% rename from app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-f612c8e8deb350eb4aaa.json rename to app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-755384221a37a352fad1.json index a8e946a..e71c40d 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-f612c8e8deb350eb4aaa.json +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.cmake/api/v1/reply/target-kcompressor-RelWithDebInfo-755384221a37a352fad1.json @@ -227,6 +227,11 @@ "fragment" : "-Wl,--end-group", "role" : "libraries" }, + { + "backtrace" : 2, + "fragment" : "-lmediandk", + "role" : "libraries" + }, { "backtrace" : 2, "fragment" : "-landroid", diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.ninja_log b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.ninja_log index 8f026fc..71f533f 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.ninja_log +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/.ninja_log @@ -1,8 +1,12 @@ # ninja log v5 3 750 8029187976745550 CMakeFiles/kcompressor.dir/compressor_common.cpp.o e948351abac712f4 +1 90 8029506556797001 build.ninja a6235447c6f6ba26 0 798 8029187977212028 CMakeFiles/kcompressor.dir/native_compressor.cpp.o 11a9e5946f3f9e42 8 1358 8029187982797733 CMakeFiles/kcompressor.dir/image_compressor.cpp.o d8e972cfc758d537 6 1494 8029187984087538 CMakeFiles/kcompressor.dir/video_compressor.cpp.o 6f7ed18233f2755 1494 1770 8029187985812012 D:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/x86_64/libkcompressor.so c324cc0b7c1e37af -0 9 0 clean 267b28daf0e986 0 7 0 clean 267b28daf0e986 +0 92 8029506556797001 build.ninja a6235447c6f6ba26 +0 7 0 clean 267b28daf0e986 +0 9 0 clean 267b28daf0e986 +0 8 0 clean 267b28daf0e986 diff --git a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/build.ninja b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/build.ninja index c5be8f5..da2230e 100644 --- a/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/build.ninja +++ b/app/.cxx/RelWithDebInfo/1j3m5w6j/x86_64/build.ninja @@ -56,8 +56,6 @@ build CMakeFiles/kcompressor.dir/native_compressor.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\x86_64\libkcompressor.pdb build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/compressor_common.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -66,8 +64,6 @@ build CMakeFiles/kcompressor.dir/compressor_common.cpp.o: CXX_COMPILER__kcompres INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\x86_64\libkcompressor.pdb build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/video_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -76,8 +72,6 @@ build CMakeFiles/kcompressor.dir/video_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\x86_64\libkcompressor.pdb build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompressor_RelWithDebInfo D$:/MyProject/kcompressor/app/src/main/cpp/image_compressor.cpp || cmake_object_order_depends_target_kcompressor DEFINES = -Dkcompressor_EXPORTS @@ -86,8 +80,6 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress INCLUDES = -ID:/MyProject/kcompressor/app/src/main/cpp -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x264 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/include/x265 -ID:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/include OBJECT_DIR = CMakeFiles\kcompressor.dir OBJECT_FILE_DIR = CMakeFiles\kcompressor.dir - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\x86_64\libkcompressor.pdb # ============================================================================= @@ -100,15 +92,14 @@ build CMakeFiles/kcompressor.dir/image_compressor.cpp.o: CXX_COMPILER__kcompress build D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDebInfo/1j3m5w6j/obj/x86_64/libkcompressor.so: CXX_SHARED_LIBRARY_LINKER__kcompressor_RelWithDebInfo CMakeFiles/kcompressor.dir/native_compressor.cpp.o CMakeFiles/kcompressor.dir/compressor_common.cpp.o CMakeFiles/kcompressor.dir/video_compressor.cpp.o CMakeFiles/kcompressor.dir/image_compressor.cpp.o | D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libx264.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libx265.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libturbojpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libjpeg.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libwebp.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libsharpyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libavif.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libaom.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libyuv.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libimagequant.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/liboxipng_ffi.a D$:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libkimage_png.a LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++17 -fexceptions -frtti -O2 -g -DNDEBUG LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,--gc-sections - LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libkimage_png.a -Wl,--end-group -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm + LINK_LIBRARIES = -Wl,--start-group D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libx264.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libx265.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libturbojpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libjpeg.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libwebp.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libsharpyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libavif.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libaom.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libyuv.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libimagequant.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/liboxipng_ffi.a D:/MyProject/kcompressor/app/src/main/cpp/third_party/android-image-compres/x86_64/lib/libkimage_png.a -Wl,--end-group -lmediandk -landroid -llog -lz -lm -ldl -latomic -lc++_static -latomic -lm OBJECT_DIR = CMakeFiles\kcompressor.dir POST_BUILD = cd . PRE_LINK = cd . SONAME = libkcompressor.so SONAME_FLAG = -Wl,-soname, - TARGET_COMPILE_PDB = CMakeFiles\kcompressor.dir\ TARGET_FILE = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\x86_64\libkcompressor.so - TARGET_PDB = D:\MyProject\kcompressor\app\build\intermediates\cxx\RelWithDebInfo\1j3m5w6j\obj\x86_64\libkcompressor.pdb + TARGET_PDB = kcompressor.so.dbg ############################################# @@ -157,14 +148,14 @@ build all: phony D$:/MyProject/kcompressor/app/build/intermediates/cxx/RelWithDe ############################################# # Re-run CMake if any of its inputs changed. -build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt +build build.ninja: RERUN_CMAKE | CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt pool = console ############################################# # A missing CMake input file is not an error. -build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Determine.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Determine-Compiler.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony +build CMakeCache.txt CMakeFiles/3.22.1-g37088a8-dirty/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8-dirty/CMakeSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake D$:/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/abis.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android-legacy.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/android.toolchain.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/flags.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Clang.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android-Initialize.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/hooks/pre/Android.cmake D$:/Android/sdk/ndk/28.2.13676358/build/cmake/platforms.cmake D$:/MyProject/kcompressor/app/src/main/cpp/CMakeLists.txt: phony ############################################# diff --git a/app/src/main/cpp/native_compressor.cpp b/app/src/main/cpp/native_compressor.cpp index b54fb1d..b4a6ae0 100644 --- a/app/src/main/cpp/native_compressor.cpp +++ b/app/src/main/cpp/native_compressor.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "compressor_common.h" #include "video_compressor.h" @@ -7,6 +8,8 @@ extern "C" { #include +#include +#include } static std::string jstring_to_string(JNIEnv *env, jstring value, const char *fallback) { @@ -24,6 +27,42 @@ static std::string jstring_to_string(JNIEnv *env, jstring value, const char *fal return result; } + +static bool is_mediacodec_encoder_name(const std::string &encoder) { + return encoder == "h264_mediacodec" || + encoder == "hevc_mediacodec"; +} + +static const char *required_mediacodec_bsf_name(const std::string &encoder) { + if (encoder == "h264_mediacodec") { + return "h264_mp4toannexb"; + } + + if (encoder == "hevc_mediacodec") { + return "hevc_mp4toannexb"; + } + + return nullptr; +} + +static bool required_mediacodec_bsf_available(const std::string &encoder) { + const char *bsf_name = required_mediacodec_bsf_name(encoder); + if (!bsf_name) { + return true; + } + + return av_bsf_get_by_name(bsf_name) != nullptr; +} + +static std::string fallback_cpu_encoder_for(const std::string &encoder) { + if (encoder == "hevc_mediacodec" && avcodec_find_encoder_by_name("libx265")) { + return "libx265"; + } + + return "libx264"; +} + + extern "C" JNIEXPORT jboolean JNICALL Java_com_kikyps_kcompressor_NativeCompressor_isVideoEncoderAvailable(JNIEnv *env, @@ -36,7 +75,19 @@ Java_com_kikyps_kcompressor_NativeCompressor_isVideoEncoderAvailable(JNIEnv *env } const AVCodec *codec = avcodec_find_encoder_by_name(encoder.c_str()); - return codec ? JNI_TRUE : JNI_FALSE; + if (!codec) { + return JNI_FALSE; + } + + // MediaCodec encoder di FFmpeg membutuhkan bitstream filter tertentu. + // Jika FFmpeg static build dibuat dengan --disable-bsfs atau BSF terkait tidak di-enable, + // avcodec_open2() dapat gagal dengan: "Bitstream filter not found". + if (is_mediacodec_encoder_name(encoder) && + !required_mediacodec_bsf_available(encoder)) { + return JNI_FALSE; + } + + return JNI_TRUE; } extern "C" @@ -71,6 +122,21 @@ Java_com_kikyps_kcompressor_NativeCompressor_compressFd(JNIEnv *env, encoder = "libx264"; } + if (is_mediacodec_encoder_name(encoder) && + !required_mediacodec_bsf_available(encoder)) { + std::string old_encoder = encoder; + encoder = fallback_cpu_encoder_for(old_encoder); + + callback_progress( + env, + callback, + 0, + std::string("Hardware GPU tidak aktif: FFmpeg build belum menyertakan bitstream filter ") + + required_mediacodec_bsf_name(old_encoder) + + ". Fallback ke CPU." + ); + } + if (targetShortSide < 0) targetShortSide = 0; if (crf < 0) crf = 26; @@ -88,6 +154,9 @@ Java_com_kikyps_kcompressor_NativeCompressor_compressFd(JNIEnv *env, audioBitrate = 128000; } + const std::string requested_encoder = encoder; + const bool requested_hardware_encoder = is_mediacodec_encoder_name(requested_encoder); + reset_cancel_requested(); int ret = compress_video_fd_impl( @@ -105,6 +174,158 @@ Java_com_kikyps_kcompressor_NativeCompressor_compressFd(JNIEnv *env, callback ); + // Runtime fallback: + // Beberapa device/FFmpeg build terlihat punya encoder MediaCodec, + // tetapi avcodec_open2() tetap gagal, misalnya: + // "Bitstream filter not found" atau error vendor MediaCodec. + // Dalam kondisi ini, ulangi otomatis memakai CPU agar compress tidak gagal total. + if (ret < 0 && requested_hardware_encoder && !is_cancel_requested()) { + std::string cpu_encoder = fallback_cpu_encoder_for(requested_encoder); + + callback_progress( + env, + callback, + 0, + std::string("Hardware GPU gagal. Fallback otomatis ke ") + + cpu_encoder + + "." + ); + + reset_cancel_requested(); + + ret = compress_video_fd_impl( + env, + static_cast(inputFd), + static_cast(outputFd), + static_cast(targetShortSide), + static_cast(inputRotationDegrees), + static_cast(crf), + 0, + cpu_encoder, + preset_str, + audio_mode, + static_cast(audioBitrate), + callback + ); + } + + return static_cast(ret); +} + +extern "C" +JNIEXPORT jint JNICALL +Java_com_kikyps_kcompressor_NativeCompressor_compressFdToPath(JNIEnv *env, + jclass, + jint inputFd, + jstring outputPath, + jint targetShortSide, + jint inputRotationDegrees, + jint crf, + jint videoBitrate, + jstring encoderName, + jstring preset, + jstring audioMode, + jint audioBitrate, + jobject callback) { + std::string output_path = jstring_to_string(env, outputPath, ""); + std::string encoder = jstring_to_string(env, encoderName, "libx264"); + std::string preset_str = jstring_to_string(env, preset, "medium"); + std::string audio_mode = jstring_to_string(env, audioMode, "copy"); + + if (output_path.empty()) { + callback_progress(env, callback, 0, "Output temp path kosong"); + return static_cast(AVERROR(EINVAL)); + } + + if (encoder != "libx264" && + encoder != "libx265" && + encoder != "h264_mediacodec" && + encoder != "hevc_mediacodec") { + encoder = "libx264"; + } + + if (is_mediacodec_encoder_name(encoder) && + !required_mediacodec_bsf_available(encoder)) { + std::string old_encoder = encoder; + encoder = fallback_cpu_encoder_for(old_encoder); + + callback_progress( + env, + callback, + 0, + std::string("Hardware GPU tidak lengkap di build FFmpeg. Fallback ke ") + + encoder + + "." + ); + } + + if (targetShortSide < 0) targetShortSide = 0; + + if (crf < 0) crf = 26; + if (crf > 51) crf = 51; + + if (videoBitrate < 0) { + videoBitrate = 0; + } + + if (audio_mode != "copy" && audio_mode != "aac" && audio_mode != "mute") { + audio_mode = "copy"; + } + + if (audioBitrate <= 0) { + audioBitrate = 128000; + } + + const std::string requested_encoder = encoder; + const bool requested_hardware_encoder = is_mediacodec_encoder_name(requested_encoder); + + reset_cancel_requested(); + + int ret = compress_video_fd_to_path_impl( + env, + static_cast(inputFd), + output_path, + static_cast(targetShortSide), + static_cast(inputRotationDegrees), + static_cast(crf), + static_cast(videoBitrate), + encoder, + preset_str, + audio_mode, + static_cast(audioBitrate), + callback + ); + + if (ret < 0 && requested_hardware_encoder && !is_cancel_requested()) { + std::string cpu_encoder = fallback_cpu_encoder_for(requested_encoder); + + callback_progress( + env, + callback, + 0, + std::string("Hardware GPU gagal. Fallback otomatis ke ") + + cpu_encoder + + "." + ); + + reset_cancel_requested(); + + ret = compress_video_fd_to_path_impl( + env, + static_cast(inputFd), + output_path, + static_cast(targetShortSide), + static_cast(inputRotationDegrees), + static_cast(crf), + 0, + cpu_encoder, + preset_str, + audio_mode, + static_cast(audioBitrate), + callback + ); + } + return static_cast(ret); } diff --git a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a index a702387..ebd726b 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a and b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavcodec.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a index 625cfc4..c00852c 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a and b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavfilter.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a index 00ab71c..9a8303f 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a and b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavformat.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a index e0214d7..f24123b 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a and b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libavutil.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a index c4b4849..4356e25 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a and b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswresample.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a index 9599bdf..fe8704c 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a and b/app/src/main/cpp/third_party/ffmpeg-android/arm64-v8a/lib/libswscale.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a index 18dd411..01923ab 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a and b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavcodec.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a index 3b5729b..f704b35 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a and b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavfilter.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a index fb70e48..c2fd7c8 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a and b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavformat.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a index f43371a..12cbe2d 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a and b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libavutil.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a index 69e5760..5235759 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a and b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswresample.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a index 3af3680..6b42a77 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a and b/app/src/main/cpp/third_party/ffmpeg-android/armeabi-v7a/lib/libswscale.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a index e4a1092..bfad265 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavcodec.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a index ad8bfe8..87fb593 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavfilter.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a index 23cfb96..3f129a0 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavformat.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a index 5923ce6..b6ae2d0 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libavutil.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a index c165189..2ab06e7 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswresample.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a index 65658ac..34237bd 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86/lib/libswscale.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a index 5294f0f..948ae37 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavcodec.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a index aabe389..5e61427 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavfilter.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a index 5e5972c..2b28288 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavformat.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a index 6a1030d..9525c26 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libavutil.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a index 655062e..4d19e8c 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswresample.a differ diff --git a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a index b3f7009..098916b 100644 Binary files a/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a and b/app/src/main/cpp/third_party/ffmpeg-android/x86_64/lib/libswscale.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jconfig.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jconfig.h new file mode 100644 index 0000000..17f95c8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jconfig.h @@ -0,0 +1,60 @@ +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ +#define JPEG_LIB_VERSION 80 + +/* libjpeg-turbo version */ +#define LIBJPEG_TURBO_VERSION 3.1.90 + +/* libjpeg-turbo version in integer form */ +#define LIBJPEG_TURBO_VERSION_NUMBER 3001090 + +/* Support arithmetic encoding when using 8-bit samples */ +#define C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding when using 8-bit samples */ +#define D_ARITH_CODING_SUPPORTED 1 + +/* Support in-memory source/destination managers */ +#define MEM_SRCDST_SUPPORTED 1 + +/* Use accelerated SIMD routines when using 8-bit samples */ +/* #undef WITH_SIMD */ + +/* This version of libjpeg-turbo supports run-time selection of data precision, + * so BITS_IN_JSAMPLE is no longer used to specify the data precision at build + * time. However, some downstream software expects the macro to be defined. + * Since 12-bit data precision is an opt-in feature that requires explicitly + * calling 12-bit-specific libjpeg API functions and using 12-bit-specific data + * types, the unmodified portion of the libjpeg API still behaves as if it were + * built for 8-bit precision, and JSAMPLE is still literally an 8-bit data + * type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here. + */ +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif + +#ifdef _WIN32 + +#undef RIGHT_SHIFT_IS_UNSIGNED + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + +/* Define "INT32" as int, not long, per Windows custom */ +#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ +typedef short INT16; +typedef signed int INT32; +#endif +#define XMD_H /* prevent jmorecfg.h from redefining it */ + +#else + +/* Define if your (broken) compiler shifts signed values as if they were + unsigned. */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jerror.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jerror.h new file mode 100644 index 0000000..892edc3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jerror.h @@ -0,0 +1,336 @@ +/* + * jerror.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2014, 2017, 2021-2023, 2026, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code, string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code, string) code, + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented") +#endif +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#endif +JMESSAGE(JERR_BAD_DCT_COEF, + "DCT coefficient (lossy) or spatial difference (lossless) out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive/lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Requested features are incompatible") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Memory limit exceeded") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED) +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +#endif +JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_RESTART, + "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT3(cinfo, code, p1, p2, p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXITS(cinfo, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX - 1), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo, lvl, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS1(cinfo, lvl, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS2(cinfo, lvl, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMSS(cinfo, lvl, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jmorecfg.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jmorecfg.h new file mode 100644 index 0000000..a4df71c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jmorecfg.h @@ -0,0 +1,389 @@ +/* + * jmorecfg.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, 2026, + * D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255. + * However, darn few applications need more than 4 channels (maybe 5 for CMYK + + * alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +/* JSAMPLE should be the smallest type that will hold the values 0..255. */ + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int)(value)) + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + + +/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */ + +typedef short J12SAMPLE; + +#define MAXJ12SAMPLE 4095 +#define CENTERJ12SAMPLE 2048 + + +/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */ + +typedef unsigned short J16SAMPLE; + +#define MAXJ16SAMPLE 65535 +#define CENTERJ16SAMPLE 32768 + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +typedef unsigned char UINT8; + +/* UINT16 must hold at least the values 0..65535. */ + +typedef unsigned short UINT16; + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. + * + * NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were + * sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to + * long. It also wasn't common (or at least as common) in 1994 for INT32 to be + * defined by platform headers. Since then, however, INT32 is defined in + * several other common places: + * + * Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on + * 32-bit platforms (i.e always a 32-bit signed type.) + * + * basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type + * on modern platforms.) + * + * qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on + * modern platforms.) + * + * This is a recipe for conflict, since "long" and "int" aren't always + * compatible types. Since the definition of INT32 has technically been part + * of the libjpeg API for more than 20 years, we can't remove it, but we do not + * use it internally any longer. We instead define a separate type (JLONG) + * for internal use, which ensures that internal behavior will always be the + * same regardless of any external headers that may be included. + */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. (Note that changing this datatype will + * potentially require modifying the SIMD code. The x86-64 SIMD extensions, + * in particular, assume a 32-bit JDIMENSION.) + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JMETHOD(type, methodname, arglist) type (*methodname) arglist + + +/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS), + * but again, some software relies on this macro. + */ + +#undef FAR +#define FAR + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* accurate integer method */ +#define DCT_IFAST_SUPPORTED /* less accurate int method [legacy feature] */ +#define DCT_FLOAT_SUPPORTED /* floating-point method [legacy feature] */ + +/* Encoder capability options: */ + +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + C_MULTISCAN_FILES_SUPPORTED and + ENTROPY_OPT_SUPPORTED) */ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for lossless JPEG: the default tables don't + * work for lossless mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires + DCT_ISLOW_SUPPORTED) */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial + * feature of libjpeg. The idea was that, if an application developer needed + * to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could + * change these macros, rebuild libjpeg, and link their application statically + * with it. In reality, few people ever did this, because there were some + * severe restrictions involved (cjpeg and djpeg no longer worked properly, + * compressing/decompressing RGB JPEGs no longer worked properly, and the color + * quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since + * all of the O/S-supplied versions of libjpeg were built with the default + * values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications + * have come to regard these values as immutable. + * + * The libjpeg-turbo colorspace extensions provide a much cleaner way of + * compressing from/decompressing to buffers with arbitrary component orders + * and pixel sizes. Thus, we do not support changing the values of RGB_RED, + * RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions + * listed above, changing these values will also break the SIMD extensions and + * the regression tests. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + +#define JPEG_NUMCS 17 + +#define EXT_RGB_RED 0 +#define EXT_RGB_GREEN 1 +#define EXT_RGB_BLUE 2 +#define EXT_RGB_PIXELSIZE 3 + +#define EXT_RGBX_RED 0 +#define EXT_RGBX_GREEN 1 +#define EXT_RGBX_BLUE 2 +#define EXT_RGBX_PIXELSIZE 4 + +#define EXT_BGR_RED 2 +#define EXT_BGR_GREEN 1 +#define EXT_BGR_BLUE 0 +#define EXT_BGR_PIXELSIZE 3 + +#define EXT_BGRX_RED 2 +#define EXT_BGRX_GREEN 1 +#define EXT_BGRX_BLUE 0 +#define EXT_BGRX_PIXELSIZE 4 + +#define EXT_XBGR_RED 3 +#define EXT_XBGR_GREEN 2 +#define EXT_XBGR_BLUE 1 +#define EXT_XBGR_PIXELSIZE 4 + +#define EXT_XRGB_RED 1 +#define EXT_XRGB_GREEN 2 +#define EXT_XRGB_BLUE 3 +#define EXT_XRGB_PIXELSIZE 4 + +static const int rgb_red[JPEG_NUMCS] = { + -1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED, + EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + -1 +}; + +static const int rgb_green[JPEG_NUMCS] = { + -1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN, + EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + -1 +}; + +static const int rgb_blue[JPEG_NUMCS] = { + -1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE, + EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + -1 +}; + +static const int rgb_pixelsize[JPEG_NUMCS] = { + -1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE, + EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + -1 +}; + +/* Definitions for speed-related optimizations. */ + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#ifndef WITH_SIMD +#define MULTIPLIER int /* type for fastest integer multiply */ +#else +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +#endif +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + */ + +#ifndef FAST_FLOAT +#define FAST_FLOAT float +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jpeglib.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jpeglib.h new file mode 100644 index 0000000..f7076a1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/jpeglib.h @@ -0,0 +1,1223 @@ +/* + * jpeglib.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022-2024, + D. R. Commander. + * Copyright (C) 2015, Google, Inc. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +/* NOTE: This header file does not include stdio.h, despite the fact that it + * uses FILE and size_t. That is by design, since the libjpeg API predates the + * widespread adoption of ANSI/ISO C. Referring to libjpeg.txt, it is a + * documented requirement that calling programs "include system headers that + * define at least the typedefs FILE and size_t" before including jpeglib.h. + * Technically speaking, changing that requirement by including stdio.h here + * would break backward API compatibility. Please do not file bug reports, + * feature requests, or pull requests regarding this. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +/* NOTE: In lossless mode, an MCU contains one or more samples rather than one + * or more 8x8 DCT blocks, so the term "data unit" is used to generically + * describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To + * preserve backward API/ABI compatibility, the field and macro names retain + * the "block" terminology. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + */ + +typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples with + 2-bit through 8-bit data precision. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some JSAMPLE rows (a 2-D JSAMPLE + array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D JSAMPLE array: top index is color */ + +typedef J12SAMPLE *J12SAMPROW; /* ptr to one image row of pixel samples + with 9-bit through 12-bit data + precision. */ +typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some J12SAMPLE rows (a 2-D + J12SAMPLE array) */ +typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D J12SAMPLE array: top index is + color */ + +typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of pixel samples + with 13-bit through 16-bit data + precision. */ +typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some J16SAMPLE rows (a 2-D + J16SAMPLE array) */ +typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D J16SAMPLE array: top index is + color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * In lossy mode, any dummy blocks added to complete an MCU are not counted; + * therefore these values do not depend on whether a scan is interleaved or + * not. In lossless mode, these are always equal to the image width and + * height. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a data unit in samples. Always DCTSIZE for lossy compression. + * For lossy decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values from 1 to 16 are supported. Note that different components may + * receive different IDCT scalings. In lossless mode, this is always equal + * to 1. + */ +#if JPEG_LIB_VERSION >= 70 + int DCT_h_scaled_size; + int DCT_v_scaled_size; +#else + int DCT_scaled_size; +#endif + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For lossy decompression, IDCT scaling is + * included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) + * In lossless mode, these are always equal to the image width and height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ + int last_col_width; /* # of non-dummy data units across in last MCU */ + int last_row_height; /* # of non-dummy data units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL *quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void *dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + (Ss is the predictor selection value in + lossless mode) */ + int Ah, Al; /* progressive JPEG successive approx. parms + (Al is the point transform value in lossless + mode) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct *jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET *data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +#define JCS_EXTENSIONS 1 +#define JCS_ALPHA_EXTENSIONS 1 + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue as specified by the RGB_RED, + RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_EXT_RGB, /* red/green/blue */ + JCS_EXT_RGBX, /* red/green/blue/x */ + JCS_EXT_BGR, /* blue/green/red */ + JCS_EXT_BGRX, /* blue/green/red/x */ + JCS_EXT_XBGR, /* x/blue/green/red */ + JCS_EXT_XRGB, /* x/red/green/blue */ + /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, + or JCS_EXT_XRGB during decompression, the X byte is undefined, and in + order to ensure the best performance, libjpeg-turbo can set that byte to + whatever value it wishes. Use the following colorspace constants to + ensure that the X byte is set to 0xFF, so that it can be interpreted as an + opaque alpha channel. */ + JCS_EXT_RGBA, /* red/green/blue/alpha */ + JCS_EXT_BGRA, /* blue/green/red/alpha */ + JCS_EXT_ABGR, /* alpha/blue/green/red */ + JCS_EXT_ARGB, /* alpha/red/green/blue */ + JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue + [decompression only] */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* accurate integer method */ + JDCT_IFAST, /* less accurate integer method [legacy feature] */ + JDCT_FLOAT /* floating-point method [legacy feature] */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr *err; /* Error handler module */ \ + struct jpeg_memory_mgr *mem; /* Memory manager module */ \ + struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \ + void *client_data; /* Available for use by application */ \ + boolean is_decompressor; /* So common code can tell which is which */ \ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct *j_common_ptr; +typedef struct jpeg_compress_struct *j_compress_ptr; +typedef struct jpeg_decompress_struct *j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr *dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + +#if JPEG_LIB_VERSION >= 70 + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ +#endif + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; +#if JPEG_LIB_VERSION >= 70 + int q_scale_factor[NUM_QUANT_TBLS]; +#endif + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info *scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ +#if JPEG_LIB_VERSION >= 70 + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ +#endif + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or + difference controller */ + /* The coefficient or difference controller receives data in units of MCU + * rows as defined for fully interleaved scans (whether the JPEG file is + * interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE + * sample rows of each component in an "iMCU" (interleaved MCU) row. In + * lossless mode, total_iMCU_rows is always equal to the image height. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ +#endif + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master *master; + struct jpeg_c_main_controller *main; + struct jpeg_c_prep_controller *prep; + struct jpeg_c_coef_controller *coef; + struct jpeg_marker_writer *marker; + struct jpeg_color_converter *cconvert; + struct jpeg_downsampler *downsample; + struct jpeg_forward_dct *fdct; + struct jpeg_entropy_encoder *entropy; + jpeg_scan_info *script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr *src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array + If data_precision is 12, then this is + actually a J12SAMPARRAY, so callers must + type-cast it in order to read/write 12-bit + samples from/to the array. */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + +#if JPEG_LIB_VERSION >= 80 + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ +#endif + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#else + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient or difference controller's input and output progress is + * measured in units of "iMCU" (interleaved MCU) rows. These are the same as + * MCU rows in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor + * DCT block rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. + * In lossless mode, total_iMCU_rows is always equal to the image height. + */ + + JSAMPLE *sample_range_limit; /* table for fast range-limiting + If data_precision is 9 to 12, then this is + actually a J12SAMPLE pointer, and if + data_precision is 13 to 16, then this is + actually a J16SAMPLE pointer, so callers + must type-cast it in order to read samples + from the array. */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ +#endif + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master *master; + struct jpeg_d_main_controller *main; + struct jpeg_d_coef_controller *coef; + struct jpeg_d_post_controller *post; + struct jpeg_input_controller *inputctl; + struct jpeg_marker_reader *marker; + struct jpeg_entropy_decoder *entropy; + struct jpeg_inverse_dct *idct; + struct jpeg_upsampler *upsample; + struct jpeg_color_deconverter *cconvert; + struct jpeg_color_quantizer *cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + void (*error_exit) (j_common_ptr cinfo); + /* Conditionally emit a trace or warning message */ + void (*emit_message) (j_common_ptr cinfo, int msg_level); + /* Routine that actually outputs a trace or error message */ + void (*output_message) (j_common_ptr cinfo); + /* Format a message string for the most recent JPEG error or message */ + void (*format_message) (j_common_ptr cinfo, char *buffer); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + void (*reset_error_mgr) (j_common_ptr cinfo); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const *jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const *addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + void (*progress_monitor) (j_common_ptr cinfo); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + void (*init_destination) (j_compress_ptr cinfo); + boolean (*empty_output_buffer) (j_compress_ptr cinfo); + void (*term_destination) (j_compress_ptr cinfo); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET *next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + void (*init_source) (j_decompress_ptr cinfo); + boolean (*fill_input_buffer) (j_decompress_ptr cinfo); + void (*skip_input_data) (j_decompress_ptr cinfo, long num_bytes); + boolean (*resync_to_restart) (j_decompress_ptr cinfo, int desired); + void (*term_source) (j_decompress_ptr cinfo); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control *jvirt_sarray_ptr; +typedef struct jvirt_barray_control *jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); + void *(*alloc_large) (j_common_ptr cinfo, int pool_id, + size_t sizeofobject); + /* If cinfo->data_precision is 12 or 16, then this method and the + * access_virt_sarray method actually return a J12SAMPARRAY or a + * J16SAMPARRAY, so callers must type-cast the return value in order to + * read/write 12-bit or 16-bit samples from/to the array. + */ + JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows); + JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows); + jvirt_sarray_ptr (*request_virt_sarray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + jvirt_barray_ptr (*request_virt_barray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + void (*realize_virt_arrays) (j_common_ptr cinfo); + JSAMPARRAY (*access_virt_sarray) (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + JBLOCKARRAY (*access_virt_barray) (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + void (*free_pool) (j_common_ptr cinfo, int pool_id); + void (*self_destruct) (j_common_ptr cinfo); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef boolean (*jpeg_marker_parser_method) (j_decompress_ptr cinfo); + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JPP(arglist) arglist + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version, + size_t structsize); +EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, + size_t structsize); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile); +EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, + unsigned long *outsize); +EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, + const unsigned char *inbuffer, unsigned long insize); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo, + J_COLOR_SPACE colorspace); +EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo); +EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality, + boolean force_baseline); +EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor, + boolean force_baseline); +#if JPEG_LIB_VERSION >= 70 +EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo, + boolean force_baseline); +#endif +EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline); +EXTERN(int) jpeg_quality_scaling(int quality); +EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo, + int predictor_selection_value, + int point_transform); +EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo); +EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo, + boolean write_all_tables); +EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); + +#if JPEG_LIB_VERSION >= 70 +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo); +#endif + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_raw_data(j_compress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION num_lines); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker, + unsigned int datalen); +EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo); + +/* Write ICC profile. See libjpeg.txt for usage information. */ +EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len); + + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo); +EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(void) jpeg12_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_raw_data(j_decompress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION max_lines); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number); +EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo); +EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo); +EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +#if JPEG_LIB_VERSION >= 80 +EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo); +#endif +EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo, + int marker_code, + jpeg_marker_parser_method routine); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo); +EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo, + jvirt_barray_ptr *coef_arrays); +EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, + j_compress_ptr dstinfo); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort(j_common_ptr cinfo); +EXTERN(void) jpeg_destroy(j_common_ptr cinfo); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired); + +/* Read ICC profile. See libjpeg.txt for usage information. */ +EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Buffer.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Buffer.hh new file mode 100644 index 0000000..eaa84c9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Buffer.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef BUFFER_HH +#define BUFFER_HH + +#include + +#include +#include +#include +#include + +class Buffer +{ + public: + QPDF_DLL + Buffer(); + + // Create a Buffer object whose memory is owned by the class and will be freed when the Buffer + // object is destroyed. + QPDF_DLL + Buffer(size_t size); + QPDF_DLL + Buffer(std::string&& content); + + // Create a Buffer object whose memory is owned by the caller and will not be freed when the + // Buffer is destroyed. + QPDF_DLL + Buffer(unsigned char* buf, size_t size); + QPDF_DLL + Buffer(std::string& content); + + Buffer(Buffer const&) = delete; + Buffer& operator=(Buffer const&) = delete; + + QPDF_DLL + Buffer(Buffer&&) noexcept; + QPDF_DLL + Buffer& operator=(Buffer&&) noexcept; + QPDF_DLL + ~Buffer(); + QPDF_DLL + size_t getSize() const; + QPDF_DLL + unsigned char const* getBuffer() const; + QPDF_DLL + unsigned char* getBuffer(); + + // Create a new copy of the Buffer. The new Buffer owns an independent copy of the data. + QPDF_DLL + Buffer copy() const; + + // Move the content of the Buffer. After calling this method, the Buffer will be empty if the + // buffer owns its memory. Otherwise, the Buffer will be unchanged. + QPDF_DLL + std::string move(); + + // Return a string_view to the data. + QPDF_DLL + std::string_view view() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char const* data() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char* data(); + + QPDF_DLL + bool empty() const; + + QPDF_DLL + size_t size() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/BufferInputSource.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/BufferInputSource.hh new file mode 100644 index 0000000..0b857b8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/BufferInputSource.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_BUFFERINPUTSOURCE_HH +#define QPDF_BUFFERINPUTSOURCE_HH + +#include +#include + +#include + +class QPDF_DLL_CLASS BufferInputSource: public InputSource +{ + public: + // If own_memory is true, BufferInputSource will delete the buffer when finished with it. + // Otherwise, the caller owns the memory. + QPDF_DLL + BufferInputSource(std::string const& description, Buffer* buf, bool own_memory = false); + + // NB This overload copies the string contents. + QPDF_DLL + BufferInputSource(std::string const& description, std::string const& contents); + QPDF_DLL + ~BufferInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: +#ifndef QPDF_FUTURE + bool own_memory; + std::string description; + Buffer* buf; + qpdf_offset_t cur_offset; + qpdf_offset_t max_offset; +#else + class Members; + + std::unique_ptr m; +#endif +}; + +#endif // QPDF_BUFFERINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/ClosedFileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/ClosedFileInputSource.hh new file mode 100644 index 0000000..56b2cb1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/ClosedFileInputSource.hh @@ -0,0 +1,77 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_CLOSEDFILEINPUTSOURCE_HH +#define QPDF_CLOSEDFILEINPUTSOURCE_HH + +#include + +#include + +class FileInputSource; + +// This is an input source that reads from files, like FileInputSource, except that it opens and +// closes the file surrounding every operation. This decreases efficiency, but it allows many more +// of these to exist at once than the maximum number of open file descriptors. This is used for +// merging large numbers of files. +class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource +{ + public: + QPDF_DLL + ClosedFileInputSource(char const* filename); + + ClosedFileInputSource(ClosedFileInputSource const&) = delete; + ClosedFileInputSource& operator=(ClosedFileInputSource const&) = delete; + + QPDF_DLL + ~ClosedFileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + // The file stays open between calls to stayOpen(true) and stayOpen(false). You can use this to + // surround multiple operations on a single ClosedFileInputSource to reduce the overhead of a + // separate open/close on each call. + QPDF_DLL + void stayOpen(bool); + + private: + QPDF_DLL_PRIVATE + void before(); + QPDF_DLL_PRIVATE + void after(); + + std::string filename; + qpdf_offset_t offset{0}; + std::shared_ptr fis; + bool stay_open{false}; +}; + +#endif // QPDF_CLOSEDFILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Constants.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Constants.h new file mode 100644 index 0000000..4b32713 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Constants.h @@ -0,0 +1,297 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFCONSTANTS_H +#define QPDFCONSTANTS_H + +/* + * REMEMBER: + * + * Keep this file 'C' compatible so it can be used from the C and C++ + * interfaces. + */ + +/* ****************************** NOTE ****************************** + +Tl;Dr: new values must be added to the end such that no constant's +numerical value changes, even across major releases. + +Details: + +As new values are added to existing enumerated types in this file, +it is important not to change the actual values of any constants. +This means that, in the absence of explicit assignment of values, +the order of entries can't change even across major releases. Why? +Here are the reasons: + +* Many of these constants are used by the C API. The C API is used + through foreign function call interfaces by users of other languages + who may not have access to or the ability to parse a C header file. + As such, users are likely to hard-code numerical values or create + their own constants whose values match. If we change values here, + their code would break, and there would be no way to detect it short + of noticing a bug. Furthermore, it would be difficult to write code + that properly handled more than one version of the qpdf shared + object (e.g. DLL) since the information about what version of qpdf + is involved is only available at runtime. + +- It has happened from time to time that a user builds an application + with an incorrectly installed qpdf, such as having mismatched header + files and library files. In the event that they are only using qpdf + interfaces that have been stable across the versions in question, + this turns out to be harmless. If they happen to use non-compatible + interfaces, this results usually in a failure to load or an obvious + runtime error. If we change values of constants, it is possible that + code that links and runs may have mismatched values for constants. + This would create a bug that would be extremely difficult to track + down and impossible for qpdf maintainers to reproduce. + +*/ + +/* Exit Codes from QPDFJob and the qpdf CLI */ + +enum qpdf_exit_code_e { + qpdf_exit_success = 0, + /* Normal exit codes */ + qpdf_exit_error = 2, + qpdf_exit_warning = 3, + /* For --is-encrypted and --requires-password */ + qpdf_exit_is_not_encrypted = 2, + qpdf_exit_correct_password = 3, +}; + +/* Error Codes */ + +enum qpdf_error_code_e { + qpdf_e_success = 0, + qpdf_e_internal, /* logic/programming error -- indicates bug */ + qpdf_e_system, /* I/O error, memory error, etc. */ + qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */ + qpdf_e_password, /* incorrect password for encrypted file */ + qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */ + qpdf_e_pages, /* erroneous or unsupported pages structure */ + qpdf_e_object, /* type/bounds errors accessing objects */ + qpdf_e_json, /* error in qpdf JSON */ + qpdf_e_linearization, /* linearization warning */ +}; + +/* Object Types */ + +/* PDF objects represented by QPDFObjectHandle or, in the C API, by + * qpdf_oh, have a unique type code that has one of the values in the + * list below. As new object types are added to qpdf, additional items + * may be added to the list, so code that switches on these values + * should take that into consideration. (Maintainer note: it would be + * better to call this qpdf_ot_* rather than ot_* to reduce likelihood + * of name collision, but changing the names of the values breaks + * backward compatibility.) + */ +enum qpdf_object_type_e { + /* Object types internal to qpdf */ + ot_uninitialized, + ot_reserved, + /* Object types that can occur in the main document */ + ot_null, + ot_boolean, + ot_integer, + ot_real, + ot_string, + ot_name, + ot_array, + ot_dictionary, + ot_stream, + /* Additional object types that can occur in content streams */ + ot_operator, + ot_inlineimage, + /* Object types internal to qpdf */ + ot_unresolved, + ot_destroyed, + ot_reference, +}; + +/* Write Parameters. See QPDFWriter.hh for details. */ + +enum qpdf_object_stream_e { + qpdf_o_disable = 0, /* disable object streams */ + qpdf_o_preserve, /* preserve object streams */ + qpdf_o_generate /* generate object streams */ +}; +enum qpdf_stream_data_e { + qpdf_s_uncompress = 0, /* uncompress stream data */ + qpdf_s_preserve, /* preserve stream data compression */ + qpdf_s_compress /* compress stream data */ +}; + +/* Stream data flags */ + +/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */ +enum qpdf_stream_encode_flags_e { + qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */ + qpdf_ef_normalize = 1 << 1, /* normalize content stream */ +}; +enum qpdf_stream_decode_level_e { + /* These must be in order from less to more decoding. */ + qpdf_dl_none = 0, /* preserve all stream filters */ + qpdf_dl_generalized, /* decode general-purpose filters */ + qpdf_dl_specialized, /* also decode other non-lossy filters */ + qpdf_dl_all /* also decode lossy filters */ +}; +/* For JSON encoding */ +enum qpdf_json_stream_data_e { + qpdf_sj_none = 0, + qpdf_sj_inline, + qpdf_sj_file, +}; + +/* R3 Encryption Parameters */ + +enum qpdf_r3_print_e { + qpdf_r3p_full = 0, /* allow all printing */ + qpdf_r3p_low, /* allow only low-resolution printing */ + qpdf_r3p_none /* allow no printing */ +}; + +/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It + * corresponds to options in Acrobat 5's menus. The new interface in + * QPDFWriter offers more granularity and no longer uses this type. + */ +enum qpdf_r3_modify_e /* Allowed changes: */ +{ + qpdf_r3m_all = 0, /* All editing */ + qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */ + qpdf_r3m_form, /* Fill forms, signing, assembly */ + qpdf_r3m_assembly, /* Only document assembly */ + qpdf_r3m_none /* No modifications */ +}; + +/* Form field flags from the PDF spec */ + +enum pdf_form_field_flag_e { + /* flags that apply to all form fields */ + ff_all_read_only = 1 << 0, + ff_all_required = 1 << 1, + ff_all_no_export = 1 << 2, + + /* flags that apply to fields of type /Btn (button) */ + ff_btn_no_toggle_off = 1 << 14, + ff_btn_radio = 1 << 15, + ff_btn_pushbutton = 1 << 16, + ff_btn_radios_in_unison = 1 << 17, + + /* flags that apply to fields of type /Tx (text) */ + ff_tx_multiline = 1 << 12, + ff_tx_password = 1 << 13, + ff_tx_file_select = 1 << 20, + ff_tx_do_not_spell_check = 1 << 22, + ff_tx_do_not_scroll = 1 << 23, + ff_tx_comb = 1 << 24, + ff_tx_rich_text = 1 << 25, + + /* flags that apply to fields of type /Ch (choice) */ + ff_ch_combo = 1 << 17, + ff_ch_edit = 1 << 18, + ff_ch_sort = 1 << 19, + ff_ch_multi_select = 1 << 21, + ff_ch_do_not_spell_check = 1 << 22, + ff_ch_commit_on_sel_change = 1 << 26 +}; + +/* Annotation flags from the PDF spec */ + +enum pdf_annotation_flag_e { + an_invisible = 1 << 0, + an_hidden = 1 << 1, + an_print = 1 << 2, + an_no_zoom = 1 << 3, + an_no_rotate = 1 << 4, + an_no_view = 1 << 5, + an_read_only = 1 << 6, + an_locked = 1 << 7, + an_toggle_no_view = 1 << 8, + an_locked_contents = 1 << 9 +}; + +/* Encryption/password status for QPDFJob */ +enum qpdf_encryption_status_e { qpdf_es_encrypted = 1 << 0, qpdf_es_password_incorrect = 1 << 1 }; + +/* Page label types */ +enum qpdf_page_label_e { + pl_none, + pl_digits, + pl_alpha_lower, + pl_alpha_upper, + pl_roman_lower, + pl_roman_upper, +}; + +/** + * @enum qpdf_result_e + * @brief Enum representing result codes for qpdf C-API functions. + * + * Results <= qpdf_r_no_warn indicate success without warnings, + * qpdf_r_no_warn < result <= qpdf_r_success indicates success with warnings, and + * qpdf_r_success < result indicates failure. + */ +enum qpdf_result_e { + /* success */ + qpdf_r_ok = 0, + qpdf_r_no_warn = 0xff, /// any result <= qpdf_no_warn indicates success without warning + qpdf_r_success = 0xffff, /// any result <= qpdf_r_success indicates success + /* failure */ + qpdf_r_bad_parameter = 0x10000, + + qpdf_r_no_warn_mask = 0x7fffff00, + qpdf_r_success_mask = 0x7fff0000, +}; + +/** + * @enum qpdf_param_e + * @brief This enumeration defines various parameters and configuration options for qpdf C-API + * functions. + * + * The enum values are grouped into sections based on their functionality, such as global + * options or global limits. For the meaning of individual parameters see `qpdf/global.cc` + */ +enum qpdf_param_e { + /* global state */ + qpdf_p_limit_errors = 0x10020, + + /* global options */ + qpdf_p_inspection_mode = 0x11000, + qpdf_p_default_limits = 0x11100, + /* global limits */ + + /* parser limits */ + qpdf_p_parser_max_nesting = 0x13000, + qpdf_p_parser_max_errors, + qpdf_p_parser_max_container_size, + qpdf_p_parser_max_container_size_damaged, + + /* stream and filter limits */ + qpdf_p_max_stream_filters = 0x14000, + + /* next section = 0x20000 */ + qpdf_enum_max = 0x7fffffff, +}; + +#endif /* QPDFCONSTANTS_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/DLL.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/DLL.h new file mode 100644 index 0000000..cc6dcbb --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/DLL.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDF_DLL_HH +#define QPDF_DLL_HH + +/* The first version of qpdf to include the version constants is 10.6.0. */ +#define QPDF_MAJOR_VERSION 12 +#define QPDF_MINOR_VERSION 3 +#define QPDF_PATCH_VERSION 2 + +#ifdef QPDF_FUTURE +# define QPDF_VERSION "12.3.2+future" +#else +# define QPDF_VERSION "12.3.2" +#endif + +/* + * This file defines symbols that control the which functions, + * classes, and methods are exposed to the public ABI (application + * binary interface). See below for a detailed explanation. + */ + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef libqpdf_EXPORTS +# define QPDF_DLL __declspec(dllexport) +# else +# define QPDF_DLL +# endif +# define QPDF_DLL_PRIVATE +#elif defined __GNUC__ +# define QPDF_DLL __attribute__((visibility("default"))) +# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden"))) +#else +# define QPDF_DLL +# define QPDF_DLL_PRIVATE +#endif +#ifdef __GNUC__ +# define QPDF_DLL_CLASS QPDF_DLL +#else +# define QPDF_DLL_CLASS +#endif + +/* + +Here's what's happening. See also https://gcc.gnu.org/wiki/Visibility +for a more in-depth discussion. + +* Everything in the public ABI must be exported. Things not in the + public ABI should not be exported. + +* A class's runtime type information is need if the class is going to + be used as an exception, inherited from, or tested with + dynamic_class. To do these things across a shared object boundary, + runtime type information must be exported. + +* On Windows: + + * For a symbol (function, method, etc.) to be exported into the + public ABI, it must be explicitly marked for export. + + * If you mark a class for export, all symbols in the class, + including private methods, are exported into the DLL, and there is + no way to exclude something from export. + + * A class's run-time type information is made available based on the + presence of a compiler flag (with MSVC), which is always on for + qpdf builds. + + * Marking classes for export should be done only when *building* the + DLL, not when *using* the DLL. + + * It is possible to mark symbols for import for DLL users, but it is + not necessary, and doing it right is complex in our case of being + multi-platform and building both static and shared libraries that + use the same headers, so we don't bother. + + * If we don't export base classes with mingw, the vtables don't end + up in the DLL. + +* On Linux (and other similar systems): + + * Common compilers such as gcc and clang export all symbols into the + public ABI by default. The qpdf build overrides this by using + "visibility=hidden", which makes it behave more like Windows in + that things have to be explicitly exported to appear in the public + ABI. + + * As with Windows, marking a class for export causes everything in + the class, including private methods, the be exported. However, + unlike in Windows: + + * It is possible to explicitly mark symbols as private + + * The only way to get the runtime type and vtable information into + the ABI is to mark the class as exported. + + * It is harmless and sometimes necessary to include the visibility + marks when using the library as well as when building it. In + particular, clang on MacOS requires the visibility marks to + match in both cases. + +What does this mean: + +* On Windows, we never have to export a class, and while there is no + way to "unexport" something, we also have no need to do it. + +* On non-Windows, we have to export some classes, and when we do, we + have to "unexport" some of their parts. + +* We only use the libqpdf_EXPORTS as a conditional for defining the + symbols for Windows builds. + +To achieve this, we use QPDF_DLL_CLASS to export classes, QPDF_DLL to +export methods, and QPDF_DLL_PRIVATE to unexport private methods in +exported classes. + +*/ + +#endif /* QPDF_DLL_HH */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/FileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/FileInputSource.hh new file mode 100644 index 0000000..af42400 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/FileInputSource.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_FILEINPUTSOURCE_HH +#define QPDF_FILEINPUTSOURCE_HH + +#include + +class QPDF_DLL_CLASS FileInputSource: public InputSource +{ + public: + FileInputSource() = default; + QPDF_DLL + FileInputSource(char const* filename); + QPDF_DLL + FileInputSource(char const* description, FILE* filep, bool close_file); + QPDF_DLL + void setFilename(char const* filename); + QPDF_DLL + void setFile(char const* description, FILE* filep, bool close_file); + + FileInputSource(FileInputSource const&) = delete; + FileInputSource& operator=(FileInputSource const&) = delete; + + QPDF_DLL + ~FileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: + bool close_file{false}; + std::string filename; + FILE* file{nullptr}; +}; + +#endif // QPDF_FILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/InputSource.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/InputSource.hh new file mode 100644 index 0000000..bac54ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/InputSource.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_INPUTSOURCE_HH +#define QPDF_INPUTSOURCE_HH + +#include +#include + +#include +#include +#include + +// Remember to use QPDF_DLL_CLASS on anything derived from InputSource so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS InputSource +{ + public: + InputSource() = default; + + virtual ~InputSource() = default; + + class QPDF_DLL_CLASS Finder + { + public: + QPDF_DLL + Finder() = default; + QPDF_DLL + virtual ~Finder() = default; + virtual bool check() = 0; + }; + + QPDF_DLL + void setLastOffset(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getLastOffset() const; + QPDF_DLL + std::string readLine(size_t max_line_length); + + // Find first or last occurrence of a sequence of characters starting within the range defined + // by offset and len such that, when the input source is positioned at the beginning of that + // sequence, finder.check() returns true. If len is 0, the search proceeds until EOF. If a + // qualifying pattern is found, these methods return true and leave the input source positioned + // wherever check() left it at the end of the matching pattern. + QPDF_DLL + bool findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + QPDF_DLL + bool findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + + virtual qpdf_offset_t findAndSkipNextEOL() = 0; + virtual std::string const& getName() const = 0; + virtual qpdf_offset_t tell() = 0; + virtual void seek(qpdf_offset_t offset, int whence) = 0; + virtual void rewind() = 0; + virtual size_t read(char* buffer, size_t length) = 0; + + // Note: you can only unread the character you just read. The specific character is ignored by + // some implementations, and the implementation doesn't check this. Use of unreadCh is + // semantically equivalent to seek(-1, SEEK_CUR) but is much more efficient. + virtual void unreadCh(char ch) = 0; + + // The following methods are for internal use by qpdf only. + inline size_t read(std::string& str, size_t count, qpdf_offset_t at = -1); + inline std::string read(size_t count, qpdf_offset_t at = -1); + size_t read_line(std::string& str, size_t count, qpdf_offset_t at = -1); + std::string read_line(size_t count, qpdf_offset_t at = -1); + inline qpdf_offset_t fastTell(); + inline bool fastRead(char&); + inline void fastUnread(bool); + inline void loadBuffer(); + + protected: + qpdf_offset_t last_offset{0}; + + private: + // State for fast... methods + static const qpdf_offset_t buf_size = 128; + char buffer[buf_size]; + qpdf_offset_t buf_len = 0; + qpdf_offset_t buf_idx = 0; + qpdf_offset_t buf_start = 0; +}; + +#endif // QPDF_INPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/JSON.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/JSON.hh new file mode 100644 index 0000000..3713e73 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/JSON.hh @@ -0,0 +1,404 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef JSON_HH +#define JSON_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Pipeline; +class InputSource; + +// This is a simple JSON serializer and parser, primarily designed for serializing QPDF Objects as +// JSON. While it may work as a general-purpose JSON parser/serializer, there are better options. +// JSON objects contain their data as smart pointers. When one JSON object is added to another, this +// pointer is copied. This means you can create temporary JSON objects on the stack, add them to +// other objects, and let them go out of scope safely. It also means that if a JSON object is added +// in more than one place, all copies share the underlying data. This makes them similar in +// structure and behavior to QPDFObjectHandle and may feel natural within the QPDF codebase, but it +// is also a good reason not to use this as a general-purpose JSON package. +class JSON +{ + public: + static int constexpr LATEST = 2; + + JSON() = default; + + QPDF_DLL + std::string unparse() const; + + // Write the JSON object through a pipeline. The `depth` parameter specifies how deeply nested + // this is in another JSON structure, which makes it possible to write clean-looking JSON + // incrementally. + QPDF_DLL + void write(Pipeline*, size_t depth = 0) const; + + // Helper methods for writing JSON incrementally. + // + // "first" -- Several methods take a `bool& first` parameter. The open methods always set it to + // true, and the methods to output items always set it to false. This way, the item and close + // methods can always know whether or not a first item is being written. The intended mode of + // operation is to start with a new `bool first = true` each time a new container is opened and + // to pass that `first` through to all the methods that are called to add top-level items to the + // container as well as to close the container. This lets the JSON object use it to keep track + // of when it's writing a first object and when it's not. If incrementally writing multiple + // levels of depth, a new `first` should be used for each new container that is opened. + // + // "depth" -- Indicate the level of depth. This is used for consistent indentation. When writing + // incrementally, whenever you call a method to add an item to a container, the value of `depth` + // should be one more than whatever value is passed to the container open and close methods. + + // Open methods ignore the value of first and set it to false + QPDF_DLL + static void writeDictionaryOpen(Pipeline*, bool& first, size_t depth = 0); + QPDF_DLL + static void writeArrayOpen(Pipeline*, bool& first, size_t depth = 0); + // Close methods don't modify first. A true value indicates that we are closing an empty object. + QPDF_DLL + static void writeDictionaryClose(Pipeline*, bool first, size_t depth = 0); + QPDF_DLL + static void writeArrayClose(Pipeline*, bool first, size_t depth = 0); + // The item methods use the value of first to determine if this is the first item and always set + // it to false. + QPDF_DLL + static void writeDictionaryItem( + Pipeline*, bool& first, std::string const& key, JSON const& value, size_t depth = 0); + // Write just the key of a new dictionary item, useful if writing nested structures. Calls + // writeNext. + QPDF_DLL + static void + writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth = 0); + QPDF_DLL + static void writeArrayItem(Pipeline*, bool& first, JSON const& element, size_t depth = 0); + // If writing nested structures incrementally, call writeNext before opening a new array or + // container in the midst of an existing one. The `first` you pass to writeNext should be the + // one for the parent object. The depth should be the one for the child object. Then start a new + // `first` for the nested item. Note that writeDictionaryKey and writeArrayItem call writeNext + // for you, so this is most important when writing subsequent items or container openers to an + // array. + QPDF_DLL + static void writeNext(Pipeline* p, bool& first, size_t depth = 0); + + // The JSON spec calls dictionaries "objects", but that creates too much confusion when + // referring to instances of the JSON class. + QPDF_DLL + static JSON makeDictionary(); + // addDictionaryMember returns the newly added item. + QPDF_DLL + JSON addDictionaryMember(std::string const& key, JSON const&); + QPDF_DLL + static JSON makeArray(); + // addArrayElement returns the newly added item. + QPDF_DLL + JSON addArrayElement(JSON const&); + QPDF_DLL + static JSON makeString(std::string const& utf8); + QPDF_DLL + static JSON makeInt(long long int value); + QPDF_DLL + static JSON makeReal(double value); + QPDF_DLL + static JSON makeNumber(std::string const& encoded); + QPDF_DLL + static JSON makeBool(bool value); + QPDF_DLL + static JSON makeNull(); + + // A blob serializes as a string. The function will be called by JSON with a pipeline and should + // write binary data to the pipeline but not call finish(). JSON will call finish() at the right + // time. + QPDF_DLL + static JSON makeBlob(std::function); + + QPDF_DLL + bool isArray() const; + + QPDF_DLL + bool isDictionary() const; + + // Accessors. Accessor behavior: + // + // - If argument is wrong type, including null, return false + // - If argument is right type, return true and initialize the value + + QPDF_DLL + bool getString(std::string& utf8) const; + QPDF_DLL + bool getNumber(std::string& value) const; + QPDF_DLL + bool getBool(bool& value) const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + JSON getDictItem(std::string const& key) const; + QPDF_DLL + bool forEachDictItem(std::function fn) const; + QPDF_DLL + bool forEachArrayItem(std::function fn) const; + + // Check this JSON object against a "schema". This is not a schema according to any standard. + // It's just a template of what the JSON is supposed to contain. The checking does the + // following: + // + // * The schema is a nested structure containing dictionaries, single-element arrays, and + // strings only. + // * Recursively walk the schema. In the items below, "schema object" refers to an object in + // the schema, and "checked object" refers to the corresponding part of the object being + // checked. + // * If the schema object is a dictionary, the checked object must have a dictionary in the + // same place with the same keys. If flags contains f_optional, a key in the schema does not + // have to be present in the object. Otherwise, all keys have to be present. Any key in the + // object must be present in the schema. + // * If the schema object is an array of length 1, the checked object may either be a single + // item or an array of items. The single item or each element of the checked object's + // array is validated against the single element of the schema's array. The rationale behind + // this logic is that a single element may appear wherever the schema allows a + // variable-length array. This makes it possible to start allowing an array in the future + // where a single element was previously required without breaking backward compatibility. + // * If the schema object is an array of length > 1, the checked object must be an array of + // the same length. In this case, each element of the checked object array is validated + // against the corresponding element of the schema array. + // * Otherwise, the value must be a string whose value is a description of the object's + // corresponding value, which may have any type. + // + // QPDF's JSON output conforms to certain strict compatibility rules as discussed in the manual. + // The idea is that a JSON structure created manually in qpdf.cc doubles as both JSON help + // information and a schema for validating the JSON that qpdf generates. Any discrepancies are a + // bug in qpdf. + // + // Flags is a bitwise or of values from check_flags_e. + enum check_flags_e { + f_none = 0, + f_optional = 1 << 0, + }; + QPDF_DLL + bool checkSchema(JSON schema, unsigned long flags, std::list& errors); + + // Same as passing 0 for flags + QPDF_DLL + bool checkSchema(JSON schema, std::list& errors); + + // A pointer to a Reactor class can be passed to parse, which will enable the caller to react + // to incremental events in the construction of the JSON object. This makes it possible to + // implement SAX-like handling of very large JSON objects. + class QPDF_DLL_CLASS Reactor + { + public: + virtual ~Reactor() = default; + + // The start/end methods are called when parsing of a dictionary or array is started or + // ended. The item methods are called when an item is added to a dictionary or array. When + // adding a container to another container, the item method is called with an empty + // container before the lower container's start method is called. See important notes in + // "Item methods" below. + + // During parsing of a JSON string, the parser is operating on a single object at a time. + // When a dictionary or array is started, a new context begins, and when that dictionary or + // array is ended, the previous context is resumed. So, for + // example, if you have `{"a": [1]}`, you will receive the + // following method calls + // + // dictionaryStart -- current object is the top-level dictionary + // dictionaryItem -- called with "a" and an empty array + // arrayStart -- current object is the array + // arrayItem -- called with the "1" object + // containerEnd -- now current object is the dictionary again + // containerEnd -- current object is undefined + // + // If the top-level item in a JSON string is a scalar, the topLevelScalar() method will be + // called. No argument is passed since the object is the same as what is returned by + // parse(). + + QPDF_DLL + virtual void dictionaryStart() = 0; + QPDF_DLL + virtual void arrayStart() = 0; + QPDF_DLL + virtual void containerEnd(JSON const& value) = 0; + QPDF_DLL + virtual void topLevelScalar() = 0; + + // Item methods: + // + // The return value of the item methods indicate whether the item has been "consumed". If + // the item method returns true, then the item will not be added to the containing JSON + // object. This is what allows arbitrarily large JSON objects + // to be parsed and not have to be kept in memory. + // + // NOTE: When a dictionary or an array is added to a container, the dictionaryItem or + // arrayItem method is called when the child item's start delimiter is encountered, so the + // JSON object passed in at that time will always be in its initial, empty state. + // Additionally, the child item's start method is not called until after the parent item's + // item method is called. This makes it possible to keep track of the current depth level by + // incrementing level on start methods and decrementing on end methods. + + QPDF_DLL + virtual bool dictionaryItem(std::string const& key, JSON const& value) = 0; + QPDF_DLL + virtual bool arrayItem(JSON const& value) = 0; + }; + + // Create a JSON object from a string. + QPDF_DLL + static JSON parse(std::string const&); + // Create a JSON object from an input source. See above for information about how to use the + // Reactor. + QPDF_DLL + static JSON parse(InputSource&, Reactor* reactor = nullptr); + + // parse calls setOffsets to set the inclusive start and non-inclusive end offsets of an object + // relative to its input string. Otherwise, both values are 0. + QPDF_DLL + void setStart(qpdf_offset_t); + QPDF_DLL + void setEnd(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getStart() const; + QPDF_DLL + qpdf_offset_t getEnd() const; + + // The following class does not form part of the public API and is for internal use only. + + class Writer; + + private: + static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter); + + enum value_type_e { + vt_none, + vt_dictionary, + vt_array, + vt_string, + vt_number, + vt_bool, + vt_null, + vt_blob, + }; + + struct JSON_value + { + JSON_value(value_type_e type_code) : + type_code(type_code) + { + } + virtual ~JSON_value() = default; + virtual void write(Pipeline*, size_t depth) const = 0; + const value_type_e type_code{vt_none}; + }; + struct JSON_dictionary: public JSON_value + { + JSON_dictionary() : + JSON_value(vt_dictionary) + { + } + ~JSON_dictionary() override = default; + void write(Pipeline*, size_t depth) const override; + std::map members; + }; + struct JSON_array; + struct JSON_string: public JSON_value + { + JSON_string(std::string const& utf8); + ~JSON_string() override = default; + void write(Pipeline*, size_t depth) const override; + std::string utf8; + }; + struct JSON_number: public JSON_value + { + JSON_number(long long val); + JSON_number(double val); + JSON_number(std::string const& val); + ~JSON_number() override = default; + void write(Pipeline*, size_t depth) const override; + std::string encoded; + }; + struct JSON_bool: public JSON_value + { + JSON_bool(bool val); + ~JSON_bool() override = default; + void write(Pipeline*, size_t depth) const override; + bool value; + }; + struct JSON_null: public JSON_value + { + JSON_null() : + JSON_value(vt_null) + { + } + ~JSON_null() override = default; + void write(Pipeline*, size_t depth) const override; + }; + struct JSON_blob: public JSON_value + { + JSON_blob(std::function fn); + ~JSON_blob() override = default; + void write(Pipeline*, size_t depth) const override; + std::function fn; + }; + + JSON(std::unique_ptr); + + static void checkSchemaInternal( + JSON_value* this_v, + JSON_value* sch_v, + unsigned long flags, + std::list& errors, + std::string prefix); + + class Members + { + friend class JSON; + + public: + ~Members() = default; + + private: + Members(std::unique_ptr); + Members(Members const&) = delete; + + std::unique_ptr value; + // start and end are only populated for objects created by parse + qpdf_offset_t start{0}; + qpdf_offset_t end{0}; + }; + + std::shared_ptr m; +}; + +struct JSON::JSON_array: public JSON_value +{ + JSON_array() : + JSON_value(vt_array) + { + } + ~JSON_array() override = default; + void write(Pipeline*, size_t depth) const override; + std::vector elements; +}; + +#endif // JSON_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/ObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/ObjectHandle.hh new file mode 100644 index 0000000..9cf4dc6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/ObjectHandle.hh @@ -0,0 +1,155 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef OBJECTHANDLE_HH +#define OBJECTHANDLE_HH + +#include +#include +#include + +#include +#include +#include + +#include +#include + +class QPDF; +class QPDF_Dictionary; +class QPDFObject; +class QPDFObjectHandle; + +namespace qpdf +{ + class Array; + class BaseDictionary; + class Dictionary; + class Integer; + class Stream; + + enum typed : std::uint8_t { strict = 0, any_flag = 1, optional = 2, any = 3, error = 4 }; + + // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only + // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, + // QPDFObjGen and bool. + class BaseHandle + { + friend class ::QPDF; + + public: + explicit inline operator bool() const; + inline operator QPDFObjectHandle() const; + QPDF_DLL + operator QPDFObjGen() const; + + // The rest of the header file is for qpdf internal use only. + + // Return true if both object handles refer to the same underlying object. + bool + operator==(BaseHandle const& other) const + { + return obj == other.obj; + } + + // For arrays, return the number of items in the array. + // For null-like objects, return 0. + // For all other objects, return 1. + size_t size() const; + + // Return 'true' if size() == 0. + bool + empty() const + { + return size() == 0; + } + + QPDFObjectHandle operator[](size_t n) const; + QPDFObjectHandle operator[](int n) const; + + QPDFObjectHandle& at(std::string const& key) const; + bool contains(std::string const& key) const; + size_t erase(std::string const& key); + QPDFObjectHandle& find(std::string const& key) const; + bool replace(std::string const& key, QPDFObjectHandle value); + QPDFObjectHandle const& operator[](std::string const& key) const; + + std::shared_ptr copy(bool shallow = false) const; + // Recursively remove association with any QPDF object. This method may only be called + // during final destruction. + void disconnect(bool only_direct = true); + inline QPDFObjGen id_gen() const; + inline bool indirect() const; + inline bool null() const; + inline qpdf_offset_t offset() const; + inline QPDF* qpdf() const; + inline qpdf_object_type_e raw_type_code() const; + inline qpdf_object_type_e resolved_type_code() const; + inline qpdf_object_type_e type_code() const; + std::string unparse() const; + void write_json(int json_version, JSON::Writer& p) const; + static void warn(QPDF*, QPDFExc&&); + void warn(QPDFExc&&) const; + void warn(std::string const& warning) const; + + inline std::shared_ptr const& obj_sp() const; + inline QPDFObjectHandle oh() const; + + protected: + BaseHandle() = default; + BaseHandle(std::shared_ptr const& obj) : + obj(obj) {}; + BaseHandle(std::shared_ptr&& obj) : + obj(std::move(obj)) {}; + BaseHandle(BaseHandle const&) = default; + BaseHandle& operator=(BaseHandle const&) = default; + BaseHandle(BaseHandle&&) = default; + BaseHandle& operator=(BaseHandle&&) = default; + + inline BaseHandle(QPDFObjectHandle const& oh); + inline BaseHandle(QPDFObjectHandle&& oh); + + ~BaseHandle() = default; + + template + T* as() const; + + inline void assign(qpdf_object_type_e required, BaseHandle const& other); + inline void assign(qpdf_object_type_e required, BaseHandle&& other); + + inline void nullify(); + + std::string description() const; + + inline QPDFObjectHandle const& get(std::string const& key) const; + + void no_ci_warn_if(bool condition, std::string const& warning) const; + void no_ci_stop_if(bool condition, std::string const& warning) const; + void no_ci_stop_damaged_if(bool condition, std::string const& warning) const; + std::invalid_argument invalid_error(std::string const& method) const; + std::runtime_error type_error(char const* expected_type) const; + QPDFExc type_error(char const* expected_type, std::string const& message) const; + char const* type_name() const; + + std::shared_ptr obj; + }; + +} // namespace qpdf + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/PDFVersion.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/PDFVersion.hh new file mode 100644 index 0000000..32b1df5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/PDFVersion.hh @@ -0,0 +1,65 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PDFVERSION_HH +#define PDFVERSION_HH + +#include +#include + +// Represent a PDF version. PDF versions are typically major.minor, but PDF 1.7 has several +// extension levels as the ISO 32000 spec was in progress. This class helps with comparison of +// versions. +class PDFVersion +{ + public: + PDFVersion() = default; + PDFVersion(PDFVersion const&) = default; + PDFVersion& operator=(PDFVersion const&) = default; + + QPDF_DLL + PDFVersion(int major, int minor, int extension = 0); + QPDF_DLL + bool operator<(PDFVersion const& rhs) const; + QPDF_DLL + bool operator==(PDFVersion const& rhs) const; + + // Replace this version with the other one if the other one is greater. + QPDF_DLL + void updateIfGreater(PDFVersion const& other); + + // Initialize a string and integer suitable for passing to QPDFWriter::setMinimumPDFVersion or + // QPDFWriter::forcePDFVersion. + QPDF_DLL + void getVersion(std::string& version, int& extension_level) const; + + QPDF_DLL + int getMajor() const; + QPDF_DLL + int getMinor() const; + QPDF_DLL + int getExtensionLevel() const; + + private: + int major_version{0}; + int minor_version{0}; + int extension_level{0}; +}; + +#endif // PDFVERSION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pipeline.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pipeline.hh new file mode 100644 index 0000000..6e07c4f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pipeline.hh @@ -0,0 +1,115 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PIPELINE_HH +#define PIPELINE_HH + +#include + +#include +#include + +// Generalized Pipeline interface. By convention, subclasses of Pipeline are called Pl_Something. +// +// When an instance of Pipeline is created with a pointer to a next pipeline, that pipeline writes +// its data to the next one when it finishes with it. In order to make possible a usage style in +// which a pipeline may be passed to a function which may stick other pipelines in front of it, the +// allocator of a pipeline is responsible for its destruction. In other words, one pipeline object +// does not attempt to manage the memory of its successor. +// +// The client is required to call finish() before destroying a Pipeline in order to avoid loss of +// data. A Pipeline class should not throw an exception in the destructor if this hasn't been done +// though since doing so causes too much trouble when deleting pipelines during error conditions. +// +// Some pipelines are reusable (i.e., you can call write() after calling finish() and can call +// finish() multiple times) while others are not. It is up to the caller to use a pipeline +// according to its own restrictions. +// +// Remember to use QPDF_DLL_CLASS on anything derived from Pipeline so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS Pipeline +{ + public: + QPDF_DLL + Pipeline(char const* identifier, Pipeline* next); + + virtual ~Pipeline() = default; + + // Subclasses should implement write and finish to do their jobs and then, if they are not + // end-of-line pipelines, call getNext()->write or getNext()->finish. + QPDF_DLL + virtual void write(unsigned char const* data, size_t len) = 0; + QPDF_DLL + virtual void finish() = 0; + QPDF_DLL + std::string getIdentifier() const; + + // These are convenience methods for making it easier to write certain other types of data to + // pipelines without having to cast. The methods that take char const* expect null-terminated C + // strings and do not write the null terminators. + QPDF_DLL + void writeCStr(char const* cstr); + QPDF_DLL + void writeString(std::string const&); + // This allows *p << "x" << "y" but is not intended to be a general purpose << compatible with + // ostream and does not have local awareness or the ability to be "imbued" with properties. + QPDF_DLL + Pipeline& operator<<(char const* cstr); + QPDF_DLL + Pipeline& operator<<(std::string const&); + QPDF_DLL + Pipeline& operator<<(short); + QPDF_DLL + Pipeline& operator<<(int); + QPDF_DLL + Pipeline& operator<<(long); + QPDF_DLL + Pipeline& operator<<(long long); + QPDF_DLL + Pipeline& operator<<(unsigned short); + QPDF_DLL + Pipeline& operator<<(unsigned int); + QPDF_DLL + Pipeline& operator<<(unsigned long); + QPDF_DLL + Pipeline& operator<<(unsigned long long); + + // Overloaded write to reduce casting + QPDF_DLL + void write(char const* data, size_t len); + + protected: + QPDF_DLL + Pipeline* getNext(bool allow_null = false); + + Pipeline* + next() const noexcept + { + return next_; + } + std::string identifier; + + private: + Pipeline(Pipeline const&) = delete; + Pipeline& operator=(Pipeline const&) = delete; + + Pipeline* next_; +}; + +#endif // PIPELINE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Buffer.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Buffer.hh new file mode 100644 index 0000000..b3b7ed6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Buffer.hh @@ -0,0 +1,76 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_BUFFER_HH +#define PL_BUFFER_HH + +#include +#include + +#include +#include + +// This pipeline accumulates the data passed to it into a memory buffer. Each subsequent use of +// this buffer appends to the data accumulated so far. getBuffer() may be called only after calling +// finish() and before calling any subsequent write(). At that point, a dynamically allocated +// Buffer object is returned and the internal buffer is reset. The caller is responsible for +// deleting the returned Buffer. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it. +class QPDF_DLL_CLASS Pl_Buffer: public Pipeline +{ + public: + QPDF_DLL + Pl_Buffer(char const* identifier, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_Buffer() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + + // Each call to getBuffer() resets this object -- see notes above. + // The caller is responsible for deleting the returned Buffer object. See also + // getBufferSharedPointer() and getMallocBuffer(). + QPDF_DLL + Buffer* getBuffer(); + + // Same as getBuffer but wraps the result in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // getMallocBuffer behaves in the same was as getBuffer except the buffer is allocated with + // malloc(), making it suitable for use when calling from other languages. If there is no data, + // *buf is set to a null pointer and *len is set to 0. Otherwise, *buf is a buffer of size *len + // allocated with malloc(). It is the caller's responsibility to call free() on the buffer. + QPDF_DLL + void getMallocBuffer(unsigned char** buf, size_t* len); + + // Same as getBuffer but returns the result as a string. + QPDF_DLL + std::string getString(); + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Concatenate.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Concatenate.hh new file mode 100644 index 0000000..48a7ca8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Concatenate.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_CONCATENATE_HH +#define PL_CONCATENATE_HH + +#include + +// This pipeline will drop all regular finish calls rather than passing them onto next. To finish +// downstream streams, call manualFinish. This makes it possible to pipe multiple streams (e.g. +// with QPDFObjectHandle::pipeStreamData) to a downstream like Pl_Flate that can't handle multiple +// calls to finish(). +class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline +{ + public: + QPDF_DLL + Pl_Concatenate(char const* identifier, Pipeline* next); + + QPDF_DLL + ~Pl_Concatenate() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + + QPDF_DLL + void finish() override; + + // At the very end, call manualFinish to actually finish the rest of the pipeline. + QPDF_DLL + void manualFinish(); + + private: + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Concatenate; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::unique_ptr m{nullptr}; +}; + +#endif // PL_CONCATENATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Count.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Count.hh new file mode 100644 index 0000000..2189b81 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Count.hh @@ -0,0 +1,52 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_COUNT_HH +#define PL_COUNT_HH + +#include +#include + +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Count: public Pipeline +{ + public: + QPDF_DLL + Pl_Count(char const* identifier, Pipeline* next); + QPDF_DLL + ~Pl_Count() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + // Returns the number of bytes written + QPDF_DLL + qpdf_offset_t getCount() const; + // Returns the last character written, or '\0' if no characters have been written (in which case + // getCount() returns 0) + QPDF_DLL + unsigned char getLastChar() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_COUNT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_DCT.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_DCT.hh new file mode 100644 index 0000000..48f2594 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_DCT.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DCT_HH +#define PL_DCT_HH + +#include + +#include +#include + +// jpeglib.h must be included after cstddef or else it messes up the definition of size_t. +#include + +class QPDF_DLL_CLASS Pl_DCT: public Pipeline +{ + public: + // Constructor for decompressing image data + QPDF_DLL + Pl_DCT(char const* identifier, Pipeline* next); + + // Limit the memory used by jpeglib when decompressing data. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setMemoryLimit(long limit); + + // Limit the number of scans used by jpeglib when decompressing progressive jpegs. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setScanLimit(int limit); + + // Treat corrupt data as a runtime error rather than attempting to decompress regardless. This + // is the qpdf default behaviour. To attempt to decompress corrupt data set 'treat_as_error' to + // false. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setThrowOnCorruptData(bool treat_as_error); + + class QPDF_DLL_CLASS CompressConfig + { + public: + QPDF_DLL + CompressConfig() = default; + QPDF_DLL + virtual ~CompressConfig() = default; + virtual void apply(jpeg_compress_struct*) = 0; + }; + + QPDF_DLL + static std::unique_ptr + make_compress_config(std::function); + + // Constructor for compressing image data + QPDF_DLL + Pl_DCT( + char const* identifier, + Pipeline* next, + JDIMENSION image_width, + JDIMENSION image_height, + int components, + J_COLOR_SPACE color_space, + CompressConfig* config_callback = nullptr); + + QPDF_DLL + ~Pl_DCT() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void compress(void* cinfo); + QPDF_DLL_PRIVATE + void decompress(void* cinfo); + + enum action_e { a_compress, a_decompress }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_DCT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Discard.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Discard.hh new file mode 100644 index 0000000..b0073cd --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Discard.hh @@ -0,0 +1,41 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DISCARD_HH +#define PL_DISCARD_HH + +#include + +// This pipeline discards its output. It is an end-of-line pipeline (with no next). +// +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Discard: public Pipeline +{ + public: + QPDF_DLL + Pl_Discard(); + QPDF_DLL + ~Pl_Discard() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; +}; + +#endif // PL_DISCARD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Flate.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Flate.hh new file mode 100644 index 0000000..2347a91 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Flate.hh @@ -0,0 +1,126 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef PL_FLATE_HH +#define PL_FLATE_HH + +#include +#include +#include +#include +#include + +class QPDF_DLL_CLASS Pl_Flate: public Pipeline +{ + public: + static unsigned int const def_bufsize = 65536; + + enum action_e { a_inflate, a_deflate }; + + QPDF_DLL + Pl_Flate( + char const* identifier, + Pipeline* next, + action_e action, + unsigned int out_bufsize = def_bufsize); + QPDF_DLL + ~Pl_Flate() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_Flate instances. + QPDF_DLL + static unsigned long long memory_limit(); + QPDF_DLL + static void memory_limit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + // Globally set compression level from 1 (fastest, least + // compression) to 9 (slowest, most compression). Use -1 to set + // the default compression level. This is passed directly to zlib. + // This method returns a pointer to the current Pl_Flate object so + // you can create a pipeline with + // Pl_Flate(...)->setCompressionLevel(...) + QPDF_DLL + static void setCompressionLevel(int); + + QPDF_DLL + void setWarnCallback(std::function callback); + + // Returns true if qpdf was built with zopfli support. + QPDF_DLL + static bool zopfli_supported(); + + // Returns true if zopfli is enabled. Zopfli is enabled if QPDF_ZOPFLI is set to a value other + // than "disabled" and zopfli support is compiled in. + QPDF_DLL + static bool zopfli_enabled(); + + // If zopfli is supported, returns true. Otherwise, check the QPDF_ZOPFLI + // environment variable as follows: + // - "disabled" or "silent": return true + // - "force": qpdf_exit_error, throw an exception + // - Any other value: issue a warning, and return false + QPDF_DLL + static bool zopfli_check_env(QPDFLogger* logger = nullptr); + + private: + QPDF_DLL_PRIVATE + void handleData(unsigned char const* data, size_t len, int flush); + QPDF_DLL_PRIVATE + void checkError(char const* prefix, int error_code); + QPDF_DLL_PRIVATE + void warn(char const*, int error_code); + QPDF_DLL_PRIVATE + void finish_zopfli(); + + QPDF_DLL_PRIVATE + static int compression_level; + + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Flate; + + public: + Members(size_t out_bufsize, action_e action); + ~Members(); + + private: + Members(Members const&) = delete; + + std::shared_ptr outbuf; + size_t out_bufsize; + action_e action; + bool initialized; + void* zdata; + unsigned long long written{0}; + std::function callback; + std::unique_ptr zopfli_buf; + }; + + std::unique_ptr m; +}; + +#endif // PL_FLATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Function.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Function.hh new file mode 100644 index 0000000..081a4e1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_Function.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_FUNCTION_HH +#define PL_FUNCTION_HH + +#include + +#include + +// This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can +// be reused. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". +// +// It is okay to keep calling write() after a previous write throws an exception as long as the +// delegated function allows it. +class QPDF_DLL_CLASS Pl_Function: public Pipeline +{ + public: + typedef std::function writer_t; + + // The supplied function is called every time write is called. + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_t fn); + + // The supplied C-style function is called every time write is called. The udata option is + // passed into the function with each call. If the function returns a non-zero value, a runtime + // error is thrown. + typedef int (*writer_c_t)(unsigned char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata); + typedef int (*writer_c_char_t)(char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata); + + QPDF_DLL + ~Pl_Function() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_FUNCTION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_OStream.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_OStream.hh new file mode 100644 index 0000000..0f912f7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_OStream.hh @@ -0,0 +1,50 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_OSTREAM_HH +#define PL_OSTREAM_HH + +#include + +#include + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. +// +// This pipeline is reusable. +class QPDF_DLL_CLASS Pl_OStream: public Pipeline +{ + public: + // os is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_OStream(char const* identifier, std::ostream& os); + QPDF_DLL + ~Pl_OStream() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_OSTREAM_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_QPDFTokenizer.hh new file mode 100644 index 0000000..e26b856 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_QPDFTokenizer.hh @@ -0,0 +1,59 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_QPDFTOKENIZER_HH +#define PL_QPDFTOKENIZER_HH + +#include + +#include +#include +#include + +#include + +// Tokenize the incoming text using QPDFTokenizer and pass the tokens in turn to a +// QPDFObjectHandle::TokenFilter object. All bytes of incoming content will be included in exactly +// one token and passed downstream. +// +// This is a very low-level interface for working with token filters. Most code will want to use +// QPDFObjectHandle::filterPageContents or QPDFObjectHandle::addTokenFilter. See QPDFObjectHandle.hh +// for details. +class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline +{ + public: + // Whatever pipeline is provided as "next" will be set as the pipeline that the token filter + // writes to. If next is not provided, any output written by the filter will be discarded. + QPDF_DLL + Pl_QPDFTokenizer( + char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_QPDFTokenizer() override; + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_RunLength.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_RunLength.hh new file mode 100644 index 0000000..4fc91fa --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_RunLength.hh @@ -0,0 +1,60 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_RUNLENGTH_HH +#define PL_RUNLENGTH_HH + +#include + +class QPDF_DLL_CLASS Pl_RunLength: public Pipeline +{ + public: + enum action_e { a_encode, a_decode }; + + QPDF_DLL + Pl_RunLength(char const* identifier, Pipeline* next, action_e action); + QPDF_DLL + ~Pl_RunLength() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_RunLength instances. + QPDF_DLL + static void setMemoryLimit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void encode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void decode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void flush_encode(); + + enum state_e { st_top, st_copying, st_run }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_RUNLENGTH_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_StdioFile.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_StdioFile.hh new file mode 100644 index 0000000..4c70528 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_StdioFile.hh @@ -0,0 +1,51 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. + +#ifndef PL_STDIOFILE_HH +#define PL_STDIOFILE_HH + +#include + +#include + +// +// This pipeline is reusable. +// +class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline +{ + public: + // f is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_StdioFile(char const* identifier, FILE* f); + QPDF_DLL + ~Pl_StdioFile() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + std::unique_ptr m; +}; + +#endif // PL_STDIOFILE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_String.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_String.hh new file mode 100644 index 0000000..a907b44 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Pl_String.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_STRING_HH +#define PL_STRING_HH + +#include + +#include + +// This pipeline accumulates the data passed to it into a std::string, a reference to which is +// passed in at construction. Each subsequent use of this pipeline appends to the data accumulated +// so far. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". This makes it easy to stick +// this in front of another pipeline to capture data that is written to the other pipeline without +// interfering with when finish is called on the other pipeline and without having to put a +// Pl_Concatenate after it. +class QPDF_DLL_CLASS Pl_String: public Pipeline +{ + public: + QPDF_DLL + Pl_String(char const* identifier, Pipeline* next, std::string& s); + QPDF_DLL + ~Pl_String() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_STRING_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/PointerHolder.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/PointerHolder.hh new file mode 100644 index 0000000..2df2d25 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/PointerHolder.hh @@ -0,0 +1,245 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef POINTERHOLDER_HH +#define POINTERHOLDER_HH + +#define POINTERHOLDER_IS_SHARED_POINTER + +#ifndef POINTERHOLDER_TRANSITION +// 0 = no deprecation warnings, backward-compatible API +// 1 = make PointerHolder(T*) explicit +// 2 = warn for use of getPointer() and getRefcount() +// 3 = warn for all use of PointerHolder +// 4 = don't define PointerHolder at all +# define POINTERHOLDER_TRANSITION 4 +#endif // !defined(POINTERHOLDER_TRANSITION) + +#if POINTERHOLDER_TRANSITION < 4 + +// *** WHAT IS HAPPENING *** + +// In qpdf 11, PointerHolder was replaced with std::shared_ptr +// wherever it appeared in the qpdf API. The PointerHolder object is +// now derived from std::shared_ptr to provide a backward-compatible +// interface and is mutually assignable with std::shared_ptr. Code +// that uses containers of PointerHolder will require adjustment. + +// In qpdf 11, a backward-compatible PointerHolder was provided with a +// warning if POINTERHOLDER_TRANSITION was not defined. Starting in +// qpdf 12, PointerHolder is absent if POINTERHOLDER_TRANSITION is not +// defined. In a future version of qpdf, PointerHolder will be removed +// outright if it becomes inconvenient to keep it around. + +// *** HOW TO TRANSITION *** + +// The symbol POINTERHOLDER_TRANSITION can be defined to help you +// transition your code away from PointerHolder. You can define it +// before including any qpdf header files or including its definition +// in your build configuration. If not defined, it automatically gets +// defined to 4, which excludes PointerHolder entirely. + +// If you want to work gradually to transition your code away from +// PointerHolder, you can define POINTERHOLDER_TRANSITION and fix the +// code so it compiles without warnings and works correctly. If you +// want to be able to continue to support old qpdf versions at the +// same time, you can write code like this: + +// #ifndef POINTERHOLDER_IS_SHARED_POINTER +// ... use PointerHolder as before 10.6 +// #else +// ... use PointerHolder or shared_ptr as needed +// #endif + +// Each level of POINTERHOLDER_TRANSITION exposes differences between +// PointerHolder and std::shared_ptr. The easiest way to transition is +// to increase POINTERHOLDER_TRANSITION in steps of 1 so that you can +// test and handle changes incrementally. + +// POINTERHOLDER_TRANSITION = 1 +// +// PointerHolder has an implicit constructor that takes a T*, so +// you can replace a PointerHolder's pointer by directly assigning +// a T* to it or pass a T* to a function that expects a +// PointerHolder. std::shared_ptr does not have this (risky) +// behavior. When POINTERHOLDER_TRANSITION = 1, PointerHolder's T* +// constructor is declared explicit. For compatibility with +// std::shared_ptr, you can still assign nullptr to a PointerHolder. +// Constructing all your PointerHolder instances explicitly is +// backward compatible, so you can make this change without +// conditional compilation and still use the changes with older qpdf +// versions. +// +// Also defined is a make_pointer_holder method that acts like +// std::make_shared. You can use this as well, but it is not +// compatible with qpdf prior to 10.6 and not necessary with qpdf +// newer than 10.6.3. Like std::make_shared, make_pointer_holder +// can only be used when the constructor implied by its arguments is +// public. If you previously used this, you can replace it width +// std::make_shared now. + +// POINTERHOLDER_TRANSITION = 2 +// +// std::shared_ptr has get() and use_count(). PointerHolder has +// getPointer() and getRefcount(). In 10.6.0, get() and use_count() +// were added as well. When POINTERHOLDER_TRANSITION = 2, getPointer() +// and getRefcount() are deprecated. Fix deprecation warnings by +// replacing with get() and use_count(). This breaks compatibility +// with qpdf older than 10.6. Search for CONST BEHAVIOR for an +// additional note. +// +// Once your code is clean at POINTERHOLDER_TRANSITION = 2, the only +// remaining issues that prevent simple replacement of PointerHolder +// with std::shared_ptr are shared arrays and containers, and neither +// of these are used in the qpdf API. + +// POINTERHOLDER_TRANSITION = 3 +// +// Warn for all use of PointerHolder. This helps you remove all use +// of PointerHolder from your code and use std::shared_ptr instead. +// You will also have to transition any containers of PointerHolder in +// your code. + +// POINTERHOLDER_TRANSITION = 4 +// +// Suppress definition of the PointerHolder type entirely. This is +// the default behavior starting with qpdf 12. + +// CONST BEHAVIOR + +// PointerHolder has had a long-standing bug in its const behavior. +// const PointerHolder's getPointer() method returns a T const*. +// This is incorrect and is not how regular pointers or standard +// library smart pointers behave. Making a PointerHolder const +// should prevent reassignment of its pointer but not affect the thing +// it points to. For that, use PointerHolder. The new get() +// method behaves correctly in this respect and is therefore slightly +// different from getPointer(). This shouldn't break any correctly +// written code. If you are relying on the incorrect behavior, use +// PointerHolder instead. + +# include +# include + +template +class PointerHolder: public std::shared_ptr +{ + public: +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(std::shared_ptr other) : + std::shared_ptr(other) + { + } +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# if POINTERHOLDER_TRANSITION >= 1 + explicit +# endif // POINTERHOLDER_TRANSITION >= 1 +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(T* pointer = 0) : + std::shared_ptr(pointer) + { + } + // Create a shared pointer to an array +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(bool, T* pointer) : + std::shared_ptr(pointer, std::default_delete()) + { + } + + virtual ~PointerHolder() = default; + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T* + getPointer() + { + return this->get(); + } +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T const* + getPointer() const + { + return this->get(); + } + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + int + getRefcount() const + { + return static_cast(this->use_count()); + } + + PointerHolder& + operator=(decltype(nullptr)) + { + std::shared_ptr::operator=(nullptr); + return *this; + } + T const& + operator*() const + { + return *(this->get()); + } + T& + operator*() + { + return *(this->get()); + } + + T const* + operator->() const + { + return this->get(); + } + T* + operator->() + { + return this->get(); + } +}; + +template +inline PointerHolder +make_pointer_holder(_Args&&... __args) +{ + return PointerHolder(new T(__args...)); +} + +template +PointerHolder +make_array_pointer_holder(size_t n) +{ + return PointerHolder(true, new T[n]); +} + +#endif // POINTERHOLDER_TRANSITION < 4 +#endif // POINTERHOLDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QIntC.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QIntC.hh new file mode 100644 index 0000000..cef8aca --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QIntC.hh @@ -0,0 +1,310 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QINTC_HH +#define QINTC_HH + +#include +#include +#include +#include +#include +#include +#include +#include + +// This namespace provides safe integer conversion that detects +// overflows. It uses short, cryptic names for brevity. + +namespace QIntC // QIntC = qpdf Integer Conversion +{ + // to_u is here for backward-compatibility from before we required + // C++-11. + template + class to_u + { + public: + typedef typename std::make_unsigned::type type; + }; + + // Basic IntConverter class, which converts an integer from the + // From class to one of the To class if it can be done safely and + // throws a range_error otherwise. This class is specialized for + // each permutation of signed/unsigned for the From and To + // classes. + template < + typename From, + typename To, + bool From_signed = std::numeric_limits::is_signed, + bool To_signed = std::numeric_limits::is_signed> + class IntConverter + { + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both unsigned. + if (i > std::numeric_limits::max()) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both signed. + if ((i < std::numeric_limits::min()) || (i > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is signed, and To is unsigned. If i > 0, it's safe to + // convert it to the corresponding unsigned type and to + // compare with To's max. + auto ii = static_cast::type>(i); + if ((i < 0) || (ii > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is unsigned, and to is signed. Convert To's max to the + // unsigned version of To and compare i against that. + auto maxval = static_cast::type>(std::numeric_limits::max()); + if (i > maxval) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + // Specific converters. The return type of each function must match + // the second template parameter to IntConverter. + template + inline char + to_char(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned char + to_uchar(T const& i) + { + return IntConverter::convert(i); + } + + template + inline short + to_short(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned short + to_ushort(T const& i) + { + return IntConverter::convert(i); + } + + template + inline int + to_int(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned int + to_uint(T const& i) + { + return IntConverter::convert(i); + } + + template + inline size_t + to_size(T const& i) + { + return IntConverter::convert(i); + } + + template + inline qpdf_offset_t + to_offset(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long + to_long(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long + to_ulong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long long + to_longlong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long long + to_ulonglong(T const& i) + { + return IntConverter::convert(i); + } + + template + void + range_check_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::max() - cur) < delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::min() - cur) > delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check(T const& cur, T const& delta) + { + if ((delta > 0) != (cur > 0)) { + return; + } + QIntC::range_check_error(cur, delta); + } + + template + void + range_check_subtract_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::min() + delta) > cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur + << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::max() + delta) < cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check_subtract(T const& cur, T const& delta) + { + if ((delta >= 0) == (cur >= 0)) { + return; + } + QIntC::range_check_subtract_error(cur, delta); + } +}; // namespace QIntC + +#endif // QINTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDF.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDF.hh new file mode 100644 index 0000000..5f990b7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDF.hh @@ -0,0 +1,804 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_HH +#define QPDF_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFLogger; + +class QPDF +{ + public: + // Get the current version of the QPDF software. See also qpdf/DLL.h + QPDF_DLL + static std::string const& QPDFVersion(); + + QPDF_DLL + QPDF(); + QPDF_DLL + ~QPDF(); + + QPDF_DLL + static std::shared_ptr create(); + + // Associate a file with a QPDF object and do initial parsing of the file. PDF objects are not + // read until they are needed. A QPDF object may be associated with only one file in its + // lifetime. This method must be called before any methods that potentially ask for information + // about the PDF file are called. Prior to calling this, the only methods that are allowed are + // those that set parameters. If the input file is not encrypted, either a null password or an + // empty password can be used. If the file is encrypted, either the user password or the owner + // password may be supplied. The method setPasswordIsHexKey may be called prior to calling this + // method or any of the other process methods to force the password to be interpreted as a raw + // encryption key. See comments on setPasswordIsHexKey for more information. + QPDF_DLL + void processFile(char const* filename, char const* password = nullptr); + + // Parse a PDF from a stdio FILE*. The FILE must be open in binary mode and must be seekable. + // It may be open read only. This works exactly like processFile except that the PDF file is + // read from an already opened FILE*. If close_file is true, the file will be closed at the + // end. Otherwise, the caller is responsible for closing the file. + QPDF_DLL + void processFile( + char const* description, FILE* file, bool close_file, char const* password = nullptr); + + // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except + // that the PDF file is in memory instead of on disk. The description appears in any warning or + // error message in place of the file name. The buffer is owned by the caller and must remain + // valid for the lifetime of the QPDF object. + QPDF_DLL + void processMemoryFile( + char const* description, char const* buf, size_t length, char const* password = nullptr); + + // Parse a PDF file loaded from a custom InputSource. If you have your own method of retrieving + // a PDF file, you can subclass InputSource and use this method. + QPDF_DLL + void processInputSource(std::shared_ptr, char const* password = nullptr); + + // Create a PDF from an input source that contains JSON as written by writeJSON (or qpdf + // --json-output, version 2 or higher). The JSON must be a complete representation of a PDF. See + // "qpdf JSON" in the manual for details. The input JSON may be arbitrarily large. QPDF does not + // load stream data into memory for more than one stream at a time, even if the stream data is + // specified inline. + QPDF_DLL + void createFromJSON(std::string const& json_file); + QPDF_DLL + void createFromJSON(std::shared_ptr); + + // Update a PDF from an input source that contains JSON in the same format as is written by + // writeJSON (or qpdf --json-output, version 2 or higher). Objects in the PDF and not in the + // JSON are not modified. See "qpdf JSON" in the manual for details. As with createFromJSON, the + // input JSON may be arbitrarily large. + QPDF_DLL + void updateFromJSON(std::string const& json_file); + QPDF_DLL + void updateFromJSON(std::shared_ptr); + + // Write qpdf JSON format to the pipeline "p". The only supported version is 2. The finish() + // method is not called on the pipeline. + // + // The decode_level parameter controls which streams are uncompressed in the JSON. Use + // qpdf_dl_none to preserve all stream data exactly as it appears in the input. The possible + // values for json_stream_data can be found in qpdf/Constants.h and correspond to the + // --json-stream-data command-line argument. If json_stream_data is qpdf_sj_file, file_prefix + // must be specified. Each stream will be written to a file whose path is constructed by + // appending "-nnn" to file_prefix, where "nnn" is the object number (not zero-filled). If + // wanted_objects is empty, write all objects. Otherwise, write only objects whose keys are in + // wanted_objects. Keys may be either "trailer" or of the form "obj:n n R". Invalid keys are + // ignored. This corresponds to the --json-object command-line argument. + // + // QPDF is efficient with regard to memory when writing, allowing you to write arbitrarily large + // PDF files to a pipeline. You can use a pipeline like Pl_Buffer or Pl_String to capture the + // JSON output in memory, but do so with caution as this will allocate enough memory to hold the + // entire PDF file. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // This version of writeJSON enables writing only the "qpdf" key of an in-progress dictionary. + // If the value of "complete" is true, a complete JSON object containing only the "qpdf" key is + // written to the pipeline. If the value of "complete" is false, the "qpdf" key and its value + // are written to the pipeline assuming that a dictionary is already open. The parameter + // first_key indicates whether this is the first key in an in-progress dictionary. It will be + // set to false by writeJSON. The "qpdf" key and value are written as if at depth 1 in a + // prettified JSON output. Remaining arguments are the same as the above version. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + bool complete, + bool& first_key, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // Close or otherwise release the input source. Once this has been called, no other methods of + // qpdf can be called safely except for getWarnings and anyWarnings(). After this has been + // called, it is safe to perform operations on the input file such as deleting or renaming it. + QPDF_DLL + void closeInputSource(); + + // For certain forensic or investigatory purposes, it may sometimes be useful to specify the + // encryption key directly, even though regular PDF applications do not provide a way to do + // this. Calling setPasswordIsHexKey(true) before calling any of the process methods will bypass + // the normal encryption key computation or recovery mechanisms and interpret the bytes in the + // password as a hex-encoded encryption key. Note that we hex-encode the key because it may + // contain null bytes and therefore can't be represented in a char const*. + QPDF_DLL + void setPasswordIsHexKey(bool); + + // Create a QPDF object for an empty PDF. This PDF has no pages or objects other than a minimal + // trailer, a document catalog, and a /Pages tree containing zero pages. Pages and other + // objects can be added to the file in the normal way, and the trailer and document catalog can + // be mutated. Calling this method is equivalent to calling processFile on an equivalent PDF + // file. See the pdf-create.cc example for a demonstration of how to use this method to create + // a PDF file from scratch. + QPDF_DLL + void emptyPDF(); + + // From 10.1: register a new filter implementation for a specific stream filter. You can add + // your own implementations for new filter types or override existing ones provided by the + // library. Registered stream filters are used for decoding only as you can override encoding + // with stream data providers. For example, you could use this method to add support for one of + // the other filter types by using additional third-party libraries that qpdf does not presently + // use. The standard filters are implemented using QPDFStreamFilter classes. + QPDF_DLL + static void registerStreamFilter( + std::string const& filter_name, std::function()> factory); + + // Parameter settings + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // Note that no normal QPDF operations generate output to standard output, so for applications + // that just wish to avoid creating output for warnings and don't call any check functions, + // calling setSuppressWarnings(true) is sufficient. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // If true, ignore any cross-reference streams in a hybrid file (one that contains both + // cross-reference streams and cross-reference tables). This can be useful for testing to + // ensure that a hybrid file would work with an older reader. + QPDF_DLL + void setIgnoreXRefStreams(bool); + + // By default, any warnings are issued to std::cerr or the error stream specified in a call to + // setOutputStreams as they are encountered. If this method is called with a true value, + // reporting of warnings is suppressed. You may still retrieve warnings by calling getWarnings. + QPDF_DLL + void setSuppressWarnings(bool); + + // Set the maximum number of warnings. A QPDFExc is thrown if the limit is exceeded. + QPDF_DLL + void setMaxWarnings(size_t); + + // By default, QPDF will try to recover if it finds certain types of errors in PDF files. If + // turned off, it will throw an exception on the first such problem it finds without attempting + // recovery. + QPDF_DLL + void setAttemptRecovery(bool); + + // Tell other QPDF objects that streams copied from this QPDF need to be fully copied when + // copyForeignObject is called on them. Calling setIgnoreXRefStreams(true) on a QPDF object + // makes it possible for the object and its input source to disappear before streams copied from + // it are written with the destination QPDF object. Confused? Ordinarily, if you are going to + // copy objects from a source QPDF object to a destination QPDF object using copyForeignObject + // or addPage, the source object's input source must stick around until after the destination + // PDF is written. If you call this method on the source QPDF object, it sends a signal to the + // destination object that it must fully copy the stream data when copyForeignObject. It will do + // this by making a copy in RAM. Ordinarily the stream data is copied lazily to avoid + // unnecessary duplication of the stream data. Note that the stream data is copied into RAM only + // once regardless of how many objects the stream is copied into. The result is that, if you + // called setImmediateCopyFrom(true) on a given QPDF object prior to copying any of its streams, + // you do not need to keep it or its input source around after copying its objects to another + // QPDF. This is true even if the source streams use StreamDataProvider. Note that this method + // is called on the QPDF object you are copying FROM, not the one you are copying to. The + // reasoning for this is that there's no reason a given QPDF may not get objects copied to it + // from a variety of other objects, some transient and some not. Since what's relevant is + // whether the source QPDF is transient, the method must be called on the source QPDF, not the + // destination one. This method will make a copy of the stream in RAM, so be sure you have + // enough memory to simultaneously hold all the streams you're copying. + QPDF_DLL + void setImmediateCopyFrom(bool); + + // Other public methods + + // Return the list of warnings that have been issued so far and clear the list. This method may + // be called even if processFile throws an exception. Note that if setSuppressWarnings was not + // called or was called with a false value, any warnings retrieved here will have already been + // output. + QPDF_DLL + std::vector getWarnings(); + + // Indicate whether any warnings have been issued so far. Does not clear the list of warnings. + QPDF_DLL + bool anyWarnings() const; + + // Indicate the number of warnings that have been issued since the last call to getWarnings. + // Does not clear the list of warnings. + QPDF_DLL + size_t numWarnings() const; + + // Return an application-scoped unique ID for this QPDF object. This is not a globally unique + // ID. It is constructed using a timestamp and a random number and is intended to be unique + // among QPDF objects that are created by a single run of an application. While it's very likely + // that these are actually globally unique, it is not recommended to use them for long-term + // purposes. + QPDF_DLL + unsigned long long getUniqueId() const; + + // Issue a warning on behalf of this QPDF object. It will be emitted with other warnings, + // following warning suppression rules, and it will be available with getWarnings(). + QPDF_DLL + void warn(QPDFExc const& e); + // Same as above but creates the QPDFExc object using the arguments passed to warn. The filename + // argument to QPDFExc is omitted. This method uses the filename associated with the QPDF + // object. + QPDF_DLL + void warn( + qpdf_error_code_e error_code, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // Return the filename associated with the QPDF object. + QPDF_DLL + std::string getFilename() const; + // Return PDF Version and extension level together as a PDFVersion object + QPDF_DLL + PDFVersion getVersionAsPDFVersion(); + // Return just the PDF version from the file + QPDF_DLL + std::string getPDFVersion() const; + QPDF_DLL + int getExtensionLevel(); + QPDF_DLL + QPDFObjectHandle getTrailer(); + QPDF_DLL + QPDFObjectHandle getRoot(); + QPDF_DLL + std::map getXRefTable(); + + // Public factory methods + + // Create a new stream. A subsequent call must be made to replaceStreamData() to provide data + // for the stream. The stream's dictionary may be retrieved by calling getDict(), and the + // resulting dictionary may be modified. Alternatively, you can create a new dictionary and + // call replaceDict to install it. + QPDF_DLL + QPDFObjectHandle newStream(); + + // Create a new stream. Use the given buffer as the stream data. The stream dictionary's + // /Length key will automatically be set to the size of the data buffer. If additional keys are + // required, the stream's dictionary may be retrieved by calling getDict(), and the resulting + // dictionary may be modified. This method is just a convenient wrapper around the newStream() + // and replaceStreamData(). It is a convenience methods for streams that require no parameters + // beyond the stream length. Note that you don't have to deal with compression yourself if you + // use QPDFWriter. By default, QPDFWriter will automatically compress uncompressed stream data. + // Example programs are provided that illustrate this. + QPDF_DLL + QPDFObjectHandle newStream(std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + QPDF_DLL + QPDFObjectHandle newStream(std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. + QPDF_DLL + QPDFObjectHandle newReserved(); + QPDF_DLL + QPDFObjectHandle newIndirectNull(); + + // Install this object handle as an indirect object and return an indirect reference to it. + QPDF_DLL + QPDFObjectHandle makeIndirectObject(QPDFObjectHandle); + + // Retrieve an object by object ID and generation. Returns an indirect reference to it. The + // getObject() methods were added for qpdf 11. + QPDF_DLL + QPDFObjectHandle getObject(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObject(int objid, int generation); + // These are older methods, but there is no intention to deprecate + // them. + QPDF_DLL + QPDFObjectHandle getObjectByObjGen(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObjectByID(int objid, int generation); + + // Replace the object with the given object id with the given object. The object handle passed + // in must be a direct object, though it may contain references to other indirect objects within + // it. Prior to qpdf 10.2.1, after calling this method, existing QPDFObjectHandle instances that + // pointed to the original object still pointed to the original object, resulting in confusing + // and incorrect behavior. This was fixed in 10.2.1, so existing QPDFObjectHandle objects will + // start pointing to the newly replaced object. Note that replacing an object with + // QPDFObjectHandle::newNull() effectively removes the object from the file since a non-existent + // object is treated as a null object. To replace a reserved object, call replaceReserved + // instead. + QPDF_DLL + void replaceObject(QPDFObjGen og, QPDFObjectHandle); + QPDF_DLL + void replaceObject(int objid, int generation, QPDFObjectHandle); + + // Swap two objects given by ID. Prior to qpdf 10.2.1, existing QPDFObjectHandle instances that + // reference them objects not notice the swap, but this was fixed in 10.2.1. + QPDF_DLL + void swapObjects(QPDFObjGen og1, QPDFObjGen og2); + QPDF_DLL + void swapObjects(int objid1, int generation1, int objid2, int generation2); + + // Replace a reserved object. This is a wrapper around replaceObject but it guarantees that the + // underlying object is a reserved object or a null object. After this call, reserved will + // be a reference to replacement. + QPDF_DLL + void replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement); + + // Copy an object from another QPDF to this one. Starting with qpdf version 8.3.0, it is no + // longer necessary to keep the original QPDF around after the call to copyForeignObject as long + // as the source of any copied stream data is still available. Usually this means you just have + // to keep the input file around, not the QPDF object. The exception to this is if you copy a + // stream that gets its data from a QPDFObjectHandle::StreamDataProvider. In this case only, the + // original stream's QPDF object must stick around because the QPDF object is itself the source + // of the original stream data. For a more in-depth discussion, please see the TODO file. + // Starting in 8.4.0, you can call setImmediateCopyFrom(true) on the SOURCE QPDF object (the one + // you're copying FROM). If you do this prior to copying any of its objects, then neither the + // source QPDF object nor its input source needs to stick around at all regardless of the + // source. The cost is that the stream data is copied into RAM at the time copyForeignObject is + // called. See setImmediateCopyFrom for more information. + // + // The return value of this method is an indirect reference to the copied object in this file. + // This method is intended to be used to copy non-page objects. To copy page objects, pass the + // foreign page object directly to addPage (or addPageAt). If you copy objects that contain + // references to pages, you should copy the pages first using addPage(At). Otherwise references + // to the pages that have not been copied will be replaced with nulls. It is possible to use + // copyForeignObject on page objects if you are not going to use them as pages. Doing so copies + // the object normally but does not update the page structure. For example, it is a valid use + // case to use copyForeignObject for a page that you are going to turn into a form XObject, + // though you can also use QPDFPageObjectHelper::getFormXObjectForPage for that purpose. + // + // When copying objects with this method, object structure will be preserved, so all indirectly + // referenced indirect objects will be copied as well. This includes any circular references + // that may exist. The QPDF object keeps a record of what has already been copied, so shared + // objects will not be copied multiple times. This also means that if you mutate an object that + // has already been copied and try to copy it again, it won't work since the modified object + // will not be recopied. Therefore, you should do all mutation on the original file that you + // are going to do before you start copying its objects to a new file. + QPDF_DLL + QPDFObjectHandle copyForeignObject(QPDFObjectHandle foreign); + + // Encryption support + + enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes, e_aesv3 }; + + // To be removed from the public API in qpdf 13. See + // . + class EncryptionData + { + public: + // This class holds data read from the encryption dictionary. + EncryptionData( + int V, + int R, + int Length_bytes, + int P, + std::string const& O, + std::string const& U, + std::string const& OE, + std::string const& UE, + std::string const& Perms, + std::string const& id1, + bool encrypt_metadata) : + V(V), + R(R), + Length_bytes(Length_bytes), + P(P), + O(O), + U(U), + OE(OE), + UE(UE), + Perms(Perms), + id1(id1), + encrypt_metadata(encrypt_metadata) + { + } + + int getV() const; + int getR() const; + int getLengthBytes() const; + int getP() const; + std::string const& getO() const; + std::string const& getU() const; + std::string const& getOE() const; + std::string const& getUE() const; + std::string const& getPerms() const; + std::string const& getId1() const; + bool getEncryptMetadata() const; + + void setO(std::string const&); + void setU(std::string const&); + void setV5EncryptionParameters( + std::string const& O, + std::string const& OE, + std::string const& U, + std::string const& UE, + std::string const& Perms); + + private: + EncryptionData(EncryptionData const&) = delete; + EncryptionData& operator=(EncryptionData const&) = delete; + + int V; + int R; + int Length_bytes; + int P; + std::string O; + std::string U; + std::string OE; + std::string UE; + std::string Perms; + std::string id1; + bool encrypt_metadata; + }; + QPDF_DLL + bool isEncrypted() const; + + QPDF_DLL + bool isEncrypted(int& R, int& P); + + QPDF_DLL + bool isEncrypted( + int& R, + int& P, + int& V, + encryption_method_e& stream_method, + encryption_method_e& string_method, + encryption_method_e& file_method); + + QPDF_DLL + bool ownerPasswordMatched() const; + + QPDF_DLL + bool userPasswordMatched() const; + + // Encryption permissions -- not enforced by QPDF + QPDF_DLL + bool allowAccessibility(); + QPDF_DLL + bool allowExtractAll(); + QPDF_DLL + bool allowPrintLowRes(); + QPDF_DLL + bool allowPrintHighRes(); + QPDF_DLL + bool allowModifyAssembly(); + QPDF_DLL + bool allowModifyForm(); + QPDF_DLL + bool allowModifyAnnotation(); + QPDF_DLL + bool allowModifyOther(); + QPDF_DLL + bool allowModifyAll(); + + // Helper function to trim padding from user password. Calling trim_user_password on the result + // of getPaddedUserPassword gives getTrimmedUserPassword's result. + QPDF_DLL + static void trim_user_password(std::string& user_password); + QPDF_DLL + static std::string compute_data_key( + std::string const& encryption_key, + int objid, + int generation, + bool use_aes, + int encryption_V, + int encryption_R); + + // To be removed in qpdf 13. See . + [[deprecated("to be removed in qpdf 13")]] + QPDF_DLL static std::string + compute_encryption_key(std::string const& password, EncryptionData const& data); + + QPDF_DLL + static void compute_encryption_O_U( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& O, + std::string& U); + QPDF_DLL + static void compute_encryption_parameters_V5( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& encryption_key, + std::string& O, + std::string& U, + std::string& OE, + std::string& UE, + std::string& Perms); + // Return the full user password as stored in the PDF file. For files encrypted with 40-bit or + // 128-bit keys, the user password can be recovered when the file is opened using the owner + // password. This is not possible with newer encryption formats. If you are attempting to + // recover the user password in a user-presentable form, call getTrimmedUserPassword() instead. + QPDF_DLL + std::string const& getPaddedUserPassword() const; + // Return human-readable form of user password subject to same limitations as + // getPaddedUserPassword(). + QPDF_DLL + std::string getTrimmedUserPassword() const; + // Return the previously computed or retrieved encryption key for this file + QPDF_DLL + std::string getEncryptionKey() const; + // Remove security restrictions associated with digitally signed files. From qpdf 11.7.0, this + // is called by QPDFAcroFormDocumentHelper::disableDigitalSignatures and is more useful when + // called from there than when just called by itself. + QPDF_DLL + void removeSecurityRestrictions(); + + // Linearization support + + // Returns true iff the file starts with a linearization parameter dictionary. Does no + // additional validation. + QPDF_DLL + bool isLinearized(); + + // Performs various sanity checks on a linearized file. Return true if no errors or warnings. + // Otherwise, return false and output errors and warnings to the default output stream + // (std::cout or whatever is configured in the logger). It is recommended for linearization + // errors to be treated as warnings. + QPDF_DLL + bool checkLinearization(); + + // Calls checkLinearization() and, if possible, prints normalized contents of some of the hints + // tables to the default output stream. Normalization includes adding min values to delta values + // and adjusting offsets based on the location and size of the primary hint stream. + QPDF_DLL + void showLinearizationData(); + + // Shows the contents of the cross-reference table + QPDF_DLL + void showXRefTable(); + + // Starting from qpdf 11.0 user code should not need to call this method. Before 11.0 this + // method was used to detect all indirect references to objects that don't exist and resolve + // them by replacing them with null, which is how the PDF spec says to interpret such dangling + // references. This method is called automatically when you try to add any new objects, if you + // call getAllObjects, and before a file is written. The qpdf object caches whether it has run + // this to avoid running it multiple times. Before 11.2.1 you could pass true to force it to run + // again if you had explicitly added new objects that may have additional dangling references. + QPDF_DLL + void fixDanglingReferences(bool force = false); + + // Return the approximate number of indirect objects. It is/ approximate because not all objects + // in the file are preserved in all cases, and gaps in object numbering are not preserved. + QPDF_DLL + size_t getObjectCount(); + + // Returns a list of indirect objects for every object in the xref table. Useful for discovering + // objects that are not otherwise referenced. + QPDF_DLL + std::vector getAllObjects(); + + // Optimization support -- see doc/optimization. Implemented in QPDF_optimization.cc + + // The object_stream_data map maps from a "compressed" object to the object stream that contains + // it. This enables optimize to populate the object <-> user maps with only uncompressed + // objects. If allow_changes is false, an exception will be thrown if any changes are made + // during the optimization process. This is available so that the test suite can make sure that + // a linearized file is already optimized. When called in this way, optimize() still populates + // the object <-> user maps. The optional skip_stream_parameters parameter, if present, is + // called for each stream object. The function should return 2 if optimization should discard + // /Length, /Filter, and /DecodeParms; 1 if it should discard /Length, and 0 if it should + // preserve all keys. This is used by QPDFWriter to avoid creation of dangling objects for + // stream dictionary keys it will be regenerating. + [[deprecated("Unused - see release notes for qpdf 12.1.0")]] QPDF_DLL void optimize( + std::map const& object_stream_data, + bool allow_changes = true, + std::function skip_stream_parameters = nullptr); + + // Traverse page tree return all /Page objects. It also detects and resolves cases in which the + // same /Page object is duplicated. For efficiency, this method returns a const reference to an + // internal vector of pages. Calls to addPage, addPageAt, and removePage safely update this, but + // direct manipulation of the pages tree or pushing inheritable objects to the page level may + // invalidate it. See comments for updateAllPagesCache() for additional notes. Newer code should + // use QPDFPageDocumentHelper::getAllPages instead. The decision to expose this internal cache + // was arguably incorrect, but it is being left here for compatibility. It is, however, + // completely safe to use this for files that you are not modifying. + QPDF_DLL + std::vector const& getAllPages(); + + QPDF_DLL + bool everCalledGetAllPages() const; + QPDF_DLL + bool everPushedInheritedAttributesToPages() const; + + // These methods, given a page object or its object/generation number, returns the 0-based index + // into the array returned by getAllPages() for that page. An exception is thrown if the page is + // not found. + QPDF_DLL + int findPage(QPDFObjGen og); + QPDF_DLL + int findPage(QPDFObjectHandle& page); + + // This method synchronizes QPDF's cache of the page structure with the actual /Pages tree. If + // you restrict changes to the /Pages tree, including addition, removal, or replacement of pages + // or changes to any /Pages objects, to calls to these page handling APIs, you never need to + // call this method. If you modify /Pages structures directly, you must call this method + // afterwards. This method updates the internal list of pages, so after calling this method, + // any previous references returned by getAllPages() will be valid again. It also resets any + // state about having pushed inherited attributes in /Pages objects down to the pages, so if you + // add any inheritable attributes to a /Pages object, you should also call this method. + QPDF_DLL + void updateAllPagesCache(); + + // Legacy handling API. These methods are not going anywhere, and you should feel free to + // continue using them if it simplifies your code. Newer code should make use of + // QPDFPageDocumentHelper instead as future page handling methods will be added there. The + // functionality and specification of these legacy methods is identical to the identically named + // methods there, except that these versions use QPDFObjectHandle instead of + // QPDFPageObjectHelper, so please see comments in that file for descriptions. There are + // subtleties you need to know about, so please look at the comments there. + QPDF_DLL + void pushInheritedAttributesToPage(); + QPDF_DLL + void addPage(QPDFObjectHandle newpage, bool first); + QPDF_DLL + void addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage); + QPDF_DLL + void removePage(QPDFObjectHandle page); + // End legacy page helpers + + // End of the public API. The following classes and methods are for qpdf internal use only. + + class Doc; + + inline Doc& doc(); + + // For testing only -- do not add to DLL + static bool test_json_validators(); + + private: + // It has never been safe to copy QPDF objects as there is code in the library that assumes + // there are no copies of a QPDF object. Copying QPDF objects was not prevented by the API until + // qpdf 11. If you have been copying QPDF objects, use std::shared_ptr instead. From qpdf + // 11, you can use QPDF::create to create them. + QPDF(QPDF const&) = delete; + QPDF& operator=(QPDF const&) = delete; + + static std::string const qpdf_version; + + class ObjCache; + class EncryptionParameters; + class StringDecrypter; + class ResolveRecorder; + class JSONReactor; + + void removeObject(QPDFObjGen og); + + // Calls finish() on the pipeline when done but does not delete it + bool pipeStreamData( + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + static bool pipeStreamData( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + + // methods to support encryption -- implemented in QPDF_encryption.cc + void initializeEncryption(); + static std::string + getKeyForObject(std::shared_ptr encp, QPDFObjGen og, bool use_aes); + void decryptString(std::string&, QPDFObjGen og); + static void decryptStream( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + Pipeline*& pipeline, + QPDFObjGen og, + QPDFObjectHandle& stream_dict, + bool is_root_metadata, + std::unique_ptr& heap); + + // JSON import + void importJSON(std::shared_ptr, bool must_be_complete); + + class Members; + + // Keep all member variables inside the Members object, which we dynamically allocate. This + // makes it possible to add new private members without breaking binary compatibility. + std::unique_ptr m; +}; + +#endif // QPDF_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFAcroFormDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFAcroFormDocumentHelper.hh new file mode 100644 index 0000000..935e161 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFAcroFormDocumentHelper.hh @@ -0,0 +1,234 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFACROFORMDOCUMENTHELPER_HH +#define QPDFACROFORMDOCUMENTHELPER_HH + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +// This document helper is intended to help with operations on interactive forms. Here are the key +// things to know: + +// * The PDF specification talks about interactive forms and also about form XObjects. While form +// XObjects appear in parts of interactive forms, this class is concerned about interactive forms, +// not form XObjects. +// +// * Interactive forms are discussed in the PDF Specification (ISO PDF 32000-1:2008) section 12.7. +// Also relevant is the section about Widget annotations. Annotations are discussed in section +// 12.5 with annotation dictionaries discussed in 12.5.1. Widget annotations are discussed +// specifically in section 12.5.6.19. +// +// * What you need to know about the structure of interactive forms in PDF files: +// +// - The document catalog contains the key "/AcroForm" which contains a list of fields. Fields are +// represented as a tree structure much like pages. Nodes in the fields tree may contain other +// fields. Fields may inherit values of many of their attributes from ancestors in the tree. +// +// - Fields may also have children that are widget annotations. As a special case, and a cause of +// considerable confusion, if a field has a single annotation as a child, the annotation +// dictionary may be merged with the field dictionary. In that case, the field and the +// annotation are in the same object. Note that, while field dictionary attributes are +// inherited, annotation dictionary attributes are not. +// +// - A page dictionary contains a key called "/Annots" which contains a simple list of +// annotations. For any given annotation of subtype "/Widget", you should encounter that +// annotation in the "/Annots" dictionary of a page, and you should also be able to reach it by +// traversing through the "/AcroForm" dictionary from the document catalog. In the simplest case +// (and also a very common case), a form field's widget annotation will be merged with the field +// object, and the object will appear directly both under "/Annots" in the page dictionary and +// under "/Fields" in the "/AcroForm" dictionary. In a more complex case, you may have to trace +// through various "/Kids" elements in the "/AcroForm" field entry until you find the annotation +// dictionary. +class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFAcroFormDocumentHelper& get(QPDF& qpdf); + + // Re-validate the AcroForm structure. This is useful if you have modified the structure of the + // AcroForm dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFAcroFormDocumentHelper(QPDF&); + + ~QPDFAcroFormDocumentHelper() override = default; + + // This class lazily creates an internal cache of the mapping among form fields, annotations, + // and pages. Methods within this class preserve the validity of this cache. However, if you + // modify pages' annotation dictionaries, the document's /AcroForm dictionary, or any form + // fields manually in a way that alters the association between forms, fields, annotations, and + // pages, it may cause this cache to become invalid. This method marks the cache invalid and + // forces it to be regenerated the next time it is needed. + QPDF_DLL + void invalidateCache(); + + QPDF_DLL + bool hasAcroForm(); + + // Add a form field, initializing the document's AcroForm dictionary if needed, updating the + // cache if necessary. Note that you are adding fields that are copies of other fields, this + // method may result in multiple fields existing with the same qualified name, which can have + // unexpected side effects. In that case, you should use addAndRenameFormFields() instead. + QPDF_DLL + void addFormField(QPDFFormFieldObjectHelper); + + // Add a collection of form fields making sure that their fully qualified names don't conflict + // with already present form fields. Fields within the collection of new fields that have the + // same name as each other will continue to do so. + QPDF_DLL + void addAndRenameFormFields(std::vector fields); + + // Remove fields from the fields array + QPDF_DLL + void removeFormFields(std::set const&); + + // Set the name of a field, updating internal records of field names. Name should be UTF-8 + // encoded. + QPDF_DLL + void setFormFieldName(QPDFFormFieldObjectHelper, std::string const& name); + + // Return a vector of all terminal fields in a document. Terminal fields are fields that have no + // children that are also fields. Terminal fields may still have children that are annotations. + // Intermediate nodes in the fields tree are not included in this list, but you can still reach + // them through the getParent method of the field object helper. + QPDF_DLL + std::vector getFormFields(); + + // Return all the form fields that have the given fully-qualified name and also have an explicit + // "/T" attribute. For this information to be accurate, any changes to field names must be done + // through setFormFieldName() above. + QPDF_DLL + std::set getFieldsWithQualifiedName(std::string const& name); + + // Return the annotations associated with a terminal field. Note that in the case of a field + // having a single annotation, the underlying object will typically be the same as the + // underlying object for the field. + QPDF_DLL + std::vector getAnnotationsForField(QPDFFormFieldObjectHelper); + + // Return annotations of subtype /Widget for a page. + QPDF_DLL + std::vector getWidgetAnnotationsForPage(QPDFPageObjectHelper); + + // Return top-level form fields for a page. + QPDF_DLL + std::vector getFormFieldsForPage(QPDFPageObjectHelper); + + // Return the terminal field that is associated with this annotation. If the annotation + // dictionary is merged with the field dictionary, the underlying object will be the same, but + // this is not always the case. Note that if you call this method with an annotation that is not + // a widget annotation, there will not be an associated field, and this method will return a + // helper associated with a null object (isNull() == true). + QPDF_DLL + QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper); + + // Return the current value of /NeedAppearances. If /NeedAppearances is missing, return false as + // that is how PDF viewers are supposed to interpret it. + QPDF_DLL + bool getNeedAppearances(); + + // Indicate whether appearance streams must be regenerated. If you modify a field value, you + // should call setNeedAppearances(true) unless you also generate an appearance stream for the + // corresponding annotation at the same time. If you generate appearance streams for all fields, + // you can call setNeedAppearances(false). If you use QPDFFormFieldObjectHelper::setV, it will + // automatically call this method unless you tell it not to. + QPDF_DLL + void setNeedAppearances(bool); + + // If /NeedAppearances is false, do nothing. Otherwise generate appearance streams for all + // widget annotations that need them. See comments in QPDFFormFieldObjectHelper.hh for + // generateAppearance for limitations. For checkbox and radio button fields, this code ensures + // that appearance state is consistent with the field's value and uses any pre-existing + // appearance streams. + QPDF_DLL + void generateAppearancesIfNeeded(); + + // Disable Digital Signature Fields. Remove all digital signature fields from the document, + // leaving any annotation showing the content of the field intact. This also calls + // QPDF::removeSecurityRestrictions. + QPDF_DLL + void disableDigitalSignatures(); + + // Note: this method works on all annotations, not just ones with associated fields. For each + // annotation in old_annots, apply the given transformation matrix to create a new annotation. + // New annotations are appended to new_annots. If the annotation is associated with a form + // field, a new form field is created that points to the new annotation and is appended to + // new_fields, and the old field is added to old_fields. + // + // old_annots may belong to a different QPDF object. In that case, you should pass in from_qpdf, + // and copyForeignObject will be called automatically. If this is the case, for efficiency, you + // may pass in a QPDFAcroFormDocumentHelper for the other file to avoid the expensive process of + // creating one for each call to transformAnnotations. New fields and annotations are not added + // to the document or pages. You have to do that yourself after calling transformAnnotations. If + // this operation will leave orphaned fields behind, such as if you are replacing the old + // annotations with the new ones on the same page and the fields and annotations are not shared, + // you will also need to remove the old fields to prevent them from hanging around unreferenced. + QPDF_DLL + void transformAnnotations( + QPDFObjectHandle old_annots, + std::vector& new_annots, + std::vector& new_fields, + std::set& old_fields, + QPDFMatrix const& cm, + QPDF* from_qpdf = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + // Copy form fields and annotations from one page to another, allowing the from page to be in a + // different QPDF or in the same QPDF. This would typically be called after calling addPage to + // add field/annotation awareness. When just copying the page by itself, annotations end up + // being shared, and fields end up being omitted because there is no reference to the field from + // the page. This method ensures that each separate copy of a page has private annotations and + // that fields and annotations are properly updated to resolve conflicts that may occur from + // common resource and field names across documents. It is basically a wrapper around + // transformAnnotations that handles updating the receiving page. If new_fields is non-null, any + // newly created fields are added to it. + QPDF_DLL + void fixCopiedAnnotations( + QPDFObjectHandle to_page, + QPDFObjectHandle from_page, + QPDFAcroFormDocumentHelper& from_afdh, + std::set* new_fields = nullptr); + + private: + friend class QPDF::Doc; + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFACROFORMDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFAnnotationObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFAnnotationObjectHelper.hh new file mode 100644 index 0000000..1f50d80 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFAnnotationObjectHelper.hh @@ -0,0 +1,105 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFANNOTATIONOBJECTHELPER_HH +#define QPDFANNOTATIONOBJECTHELPER_HH + +#include +#include + +#include + +class QPDFAnnotationObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFAnnotationObjectHelper(QPDFObjectHandle); + + ~QPDFAnnotationObjectHelper() override = default; + + // This class provides helper methods for annotations. More functionality will likely be added + // in the future. + + // Some functionality for annotations is also implemented in QPDFAcroFormDocumentHelper and + // QPDFFormFieldObjectHelper. In some cases, functions defined there work for other annotations + // besides widget annotations, but they are implemented with form fields so that they can + // properly handle form fields when needed. + + // Return the subtype of the annotation as a string (e.g. "/Widget"). Returns an empty string + // if the subtype (which is required by the spec) is missing. + QPDF_DLL + std::string getSubtype(); + + QPDF_DLL + QPDFObjectHandle::Rectangle getRect(); + + QPDF_DLL + QPDFObjectHandle getAppearanceDictionary(); + + // Return the appearance state as given in "/AS", or an empty string if none is given. + QPDF_DLL + std::string getAppearanceState(); + + // Return flags from "/F". The value is a logical or of pdf_annotation_flag_e as defined in + // qpdf/Constants.h. + QPDF_DLL + int getFlags(); + + // Return a specific stream. "which" may be one of "/N", "/R", or "/D" to indicate the normal, + // rollover, or down appearance stream. (Any value may be passed to "which"; if an appearance + // stream of that name exists, it will be returned.) If the value associated with "which" in the + // appearance dictionary is a subdictionary, an appearance state may be specified to select + // which appearance stream is desired. If not specified, the appearance state in "/AS" will + // used. + QPDF_DLL + QPDFObjectHandle getAppearanceStream(std::string const& which, std::string const& state = ""); + + // Generate text suitable for addition to the containing page's content stream that draws this + // annotation's appearance stream as a form XObject. The value "name" is the resource name that + // will be used to refer to the form xobject. The value "rotate" should be set to the page's + // /Rotate value or 0 if none. The values of required_flags and forbidden_flags are constructed + // by logically "or"ing annotation flags of type pdf_annotation_flag_e defined in + // qpdf/Constants.h. Content will be returned only if all required_flags are set and no + // forbidden_flags are set. For example, including an_no_view in forbidden_flags could be useful + // for creating an on-screen view, and including an_print to required_flags could be useful if + // preparing to print. + QPDF_DLL + std::string getPageContentForAppearance( + std::string const& name, + int rotate, + int required_flags = 0, + int forbidden_flags = an_invisible | an_hidden); + + private: + class Members + { + friend class QPDFAnnotationObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFANNOTATIONOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFCryptoImpl.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFCryptoImpl.hh new file mode 100644 index 0000000..34bbd98 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFCryptoImpl.hh @@ -0,0 +1,82 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFCRYPTOIMPL_HH +#define QPDFCRYPTOIMPL_HH + +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. +// Most users won't need to know or care about this class, but you can +// use it if you want to supply your own crypto implementation. To do +// so, provide an implementation of QPDFCryptoImpl, ensure that you +// register it by calling QPDFCryptoProvider::registerImpl, and make +// it the default by calling QPDFCryptoProvider::setDefaultProvider. +class QPDF_DLL_CLASS QPDFCryptoImpl +{ + public: + QPDFCryptoImpl() = default; + + virtual ~QPDFCryptoImpl() = default; + + // Random Number Generation + + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + // Hashing + + typedef unsigned char MD5_Digest[16]; + virtual void MD5_init() = 0; + virtual void MD5_update(unsigned char const* data, size_t len) = 0; + virtual void MD5_finalize() = 0; + virtual void MD5_digest(MD5_Digest) = 0; + + virtual void SHA2_init(int bits) = 0; + virtual void SHA2_update(unsigned char const* data, size_t len) = 0; + virtual void SHA2_finalize() = 0; + virtual std::string SHA2_digest() = 0; + + // Encryption/Decryption + + // QPDF must support RC4 to be able to work with older PDF files + // and readers. Search for RC4 in README.md + + // key_len of -1 means treat key_data as a null-terminated string + virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0; + // out_data = 0 means to encrypt/decrypt in place + virtual void + RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data = nullptr) = 0; + virtual void RC4_finalize() = 0; + + static size_t constexpr rijndael_buf_size = 16; + virtual void rijndael_init( + bool encrypt, + unsigned char const* key_data, + size_t key_len, + bool cbc_mode, + unsigned char* cbc_block) = 0; + virtual void rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0; + virtual void rijndael_finalize() = 0; +}; + +#endif // QPDFCRYPTOIMPL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFCryptoProvider.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFCryptoProvider.hh new file mode 100644 index 0000000..44d900c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFCryptoProvider.hh @@ -0,0 +1,107 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFCRYPTOPROVIDER_HH +#define QPDFCRYPTOPROVIDER_HH + +#include +#include +#include +#include +#include +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. Most users won't need to know or +// care about this class, but you can use it if you want to supply your own crypto implementation. +// See also comments in QPDFCryptoImpl.hh. +class QPDFCryptoProvider +{ + public: + // Methods for getting and registering crypto implementations. These methods are not + // thread-safe. + + // Return an instance of a crypto provider using the default implementation. + QPDF_DLL + static std::shared_ptr getImpl(); + + // Return an instance of the crypto provider registered using the given name. + QPDF_DLL + static std::shared_ptr getImpl(std::string const& name); + + typedef std::function()> provider_fn; + + // Register a crypto implementation with the given name. The provider function must return + // a shared pointer to an instance of the implementation class, which must be derived from + // QPDFCryptoImpl. + QPDF_DLL static void registerImpl(std::string const& name, provider_fn f); + + // Register the given type (T) as a crypto implementation. T must be derived from QPDFCryptoImpl + // and must have a constructor that takes no arguments. + template + static void + registerImpl(std::string const& name) + { + registerImpl(name, std::make_shared); + } + + // Set the crypto provider registered with the given name as the default crypto implementation. + QPDF_DLL + static void setDefaultProvider(std::string const& name); + + // Get the names of registered implementations + QPDF_DLL + static std::set getRegisteredImpls(); + + // Get the name of the default crypto provider + QPDF_DLL + static std::string getDefaultProvider(); + + private: + QPDFCryptoProvider(); + ~QPDFCryptoProvider() = default; + QPDFCryptoProvider(QPDFCryptoProvider const&) = delete; + QPDFCryptoProvider& operator=(QPDFCryptoProvider const&) = delete; + + static QPDFCryptoProvider& getInstance(); + + std::shared_ptr getImpl_internal(std::string const& name) const; + void registerImpl_internal(std::string const& name, provider_fn f); + void setDefaultProvider_internal(std::string const& name); + + class Members + { + friend class QPDFCryptoProvider; + + public: + Members() = default; + ~Members() = default; + + private: + Members(Members const&) = delete; + Members& operator=(Members const&) = delete; + + std::string default_provider; + std::map providers; + }; + + std::shared_ptr m; +}; + +#endif // QPDFCRYPTOPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFDocumentHelper.hh new file mode 100644 index 0000000..67d42d4 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFDocumentHelper.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFDOCUMENTHELPER_HH +#define QPDFDOCUMENTHELPER_HH + +#include +#include + +// This is a base class for QPDF Document Helper classes. Document helpers are classes that provide +// a convenient, higher-level API for accessing document-level structures within a PDF file. +// Document helpers are always initialized with a reference to a QPDF object, and the object can +// always be retrieved. The intention is that you may freely intermix use of document helpers with +// the underlying QPDF object unless there is a specific comment in a specific helper method that +// says otherwise. The pattern of using helper objects was introduced to allow creation of higher +// level helper functions without polluting the public interface of QPDF. +class QPDF_DLL_CLASS QPDFDocumentHelper +{ + public: + QPDFDocumentHelper(QPDF& qpdf) : + qpdf(qpdf) + { + } + QPDF_DLL + virtual ~QPDFDocumentHelper(); + QPDF& + getQPDF() + { + return qpdf; + } + QPDF const& + getQPDF() const + { + return qpdf; + } + + protected: + QPDF& qpdf; +}; + +#endif // QPDFDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFEFStreamObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFEFStreamObjectHelper.hh new file mode 100644 index 0000000..fec2325 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFEFStreamObjectHelper.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEFSTREAMOBJECTHELPER_HH +#define QPDFEFSTREAMOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around Embedded File Streams, which are discussed in +// section 7.11.4 of the ISO-32000 PDF specification. +class QPDFEFStreamObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFEFStreamObjectHelper(QPDFObjectHandle); + + ~QPDFEFStreamObjectHelper() override = default; + + // Date parameters are strings that conform to the PDF spec for date/time strings, which is + // "D:yyyymmddhhmmss" where is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone + // offset. Examples: "D:20210207161528-05'00'", "D:20210207211528Z". See + // QUtil::qpdf_time_to_pdf_time. + + QPDF_DLL + std::string getCreationDate(); + QPDF_DLL + std::string getModDate(); + // Get size as reported in the object; return 0 if not present. + QPDF_DLL + size_t getSize(); + // Subtype is a mime type such as "text/plain" + QPDF_DLL + std::string getSubtype(); + // Return the checksum as stored in the object as a binary string. This does not check + // consistency with the data. If not present, return an empty string. The PDF spec specifies + // this as an MD5 checksum and notes that it is not to be used for security purposes since MD5 + // is known to be insecure. + QPDF_DLL + std::string getChecksum(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // efsoh.setCreationDate(x).setModDate(y); + + // Create a new embedded file stream with the given stream data, which can be provided in any of + // several ways. To get the new object back, call getObjectHandle() on the returned object. The + // checksum and size are computed automatically and stored. Other parameters may be supplied + // using setters defined below. + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::shared_ptr data); + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::string const& data); + // The provider function must write the data to the given pipeline. The function may be called + // multiple times by the qpdf library. You can pass QUtil::file_provider(filename) as the + // provider to have the qpdf library provide the contents of filename as a binary. + QPDF_DLL + static QPDFEFStreamObjectHelper + createEFStream(QPDF& qpdf, std::function provider); + + // Setters for other parameters + QPDF_DLL + QPDFEFStreamObjectHelper& setCreationDate(std::string const&); + QPDF_DLL + QPDFEFStreamObjectHelper& setModDate(std::string const&); + + // Set subtype as a mime-type, e.g. "text/plain" or "application/pdf". + QPDF_DLL + QPDFEFStreamObjectHelper& setSubtype(std::string const&); + + private: + QPDFObjectHandle getParam(std::string const& pkey); + void setParam(std::string const& pkey, QPDFObjectHandle const&); + static QPDFEFStreamObjectHelper newFromStream(QPDFObjectHandle stream); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEFSTREAMOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh new file mode 100644 index 0000000..12174d6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh @@ -0,0 +1,90 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEMBEDDEDFILEDOCUMENTHELPER_HH +#define QPDFEMBEDDEDFILEDOCUMENTHELPER_HH + +#include + +#include +#include +#include +#include + +#include +#include + +// This class provides a higher level interface around document-level file attachments, also known +// as embedded files. These are discussed in sections 7.7.4 and 7.11 of the ISO-32000 PDF +// specification. +class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the EmbeddedFiles structure, which can be expensive. + QPDF_DLL + static QPDFEmbeddedFileDocumentHelper& get(QPDF& qpdf); + + // Re-validate the EmbeddedFiles structure. This is useful if you have modified the structure of + // the EmbeddedFiles dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFEmbeddedFileDocumentHelper(QPDF&); + + ~QPDFEmbeddedFileDocumentHelper() override = default; + + QPDF_DLL + bool hasEmbeddedFiles() const; + + QPDF_DLL + std::map> getEmbeddedFiles(); + + // If an embedded file with the given name exists, return a (shared) pointer to it. Otherwise, + // return nullptr. + QPDF_DLL + std::shared_ptr getEmbeddedFile(std::string const& name); + + // Add or replace an attachment + QPDF_DLL + void replaceEmbeddedFile(std::string const& name, QPDFFileSpecObjectHelper const&); + + // Remove an embedded file if present. Return value is true if the file was present and was + // removed. This method not only removes the embedded file from the embedded files name tree but + // also nulls out the file specification dictionary. This means that any references to this file + // from file attachment annotations will also stop working. This is the best way to make the + // attachment actually disappear from the file and not just from the list of attachments. + QPDF_DLL + bool removeEmbeddedFile(std::string const& name); + + private: + void initEmbeddedFiles(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEMBEDDEDFILEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFExc.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFExc.hh new file mode 100644 index 0000000..9038418 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFExc.hh @@ -0,0 +1,89 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEXC_HH +#define QPDFEXC_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFExc: public std::runtime_error +{ + public: + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message, + bool zero_offset_valid); + + ~QPDFExc() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. Only the error code and message are + // guaranteed to have non-zero/empty values. + + // There is no lookup code that maps numeric error codes into strings. The numeric error code + // is just another way to get at the underlying issue, but it is more programmer-friendly than + // trying to parse a string that is subject to change. + + QPDF_DLL + qpdf_error_code_e getErrorCode() const; + QPDF_DLL + std::string const& getFilename() const; + QPDF_DLL + std::string const& getObject() const; + QPDF_DLL + qpdf_offset_t getFilePosition() const; + QPDF_DLL + std::string const& getMessageDetail() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat( + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + qpdf_error_code_e error_code; + std::string filename; + std::string object; + qpdf_offset_t offset; + std::string message; +}; + +#endif // QPDFEXC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFFileSpecObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFFileSpecObjectHelper.hh new file mode 100644 index 0000000..9a00e20 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFFileSpecObjectHelper.hh @@ -0,0 +1,94 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFILESPECOBJECTHELPER_HH +#define QPDFFILESPECOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around File Specification dictionaries, which are +// discussed in section 7.11 of the ISO-32000 PDF specification. +class QPDFFileSpecObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFileSpecObjectHelper(QPDFObjectHandle); + + ~QPDFFileSpecObjectHelper() override = default; + + QPDF_DLL + std::string getDescription(); + + // Get the main filename for this file specification. In priority order, check /UF, /F, /Unix, + // /DOS, /Mac. + QPDF_DLL + std::string getFilename(); + + // Return any of /UF, /F, /Unix, /DOS, /Mac filename keys that may be present in the object. + QPDF_DLL + std::map getFilenames(); + + // Get the requested embedded file stream for this file specification. If key is empty, In + // priority order, check /UF, /F, /Unix, /DOS, /Mac. Returns a null object if not found. If this + // is an actual embedded file stream, its data is the content of the attachment. You can also + // use QPDFEFStreamObjectHelper for higher level access to the parameters. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStream(std::string const& key = ""); + + // Return the /EF key of the file spec, which is a map from file name key to embedded file + // stream. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStreams(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // fsoh.setDescription(x).setFilename(y); + + // Create a new filespec as an indirect object with the given filename, and attach the contents + // of the specified file as data in an embedded file stream. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, std::string const& fullpath); + + // Create a new filespec as an indirect object with the given unicode filename and embedded file + // stream. The file name will be used as both /UF and /F. If you need to override, call + // setFilename. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper); + + QPDF_DLL + QPDFFileSpecObjectHelper& setDescription(std::string const&); + // setFilename sets /UF to unicode_name. If compat_name is empty, it is also set to + // unicode_name. unicode_name should be a UTF-8 encoded string. compat_name is converted to a + // string QPDFObjectHandle literally, preserving whatever encoding it might happen to have. + QPDF_DLL + QPDFFileSpecObjectHelper& + setFilename(std::string const& unicode_name, std::string const& compat_name = ""); + + private: + class Members; + std::shared_ptr m; +}; + +#endif // QPDFFILESPECOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFFormFieldObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFFormFieldObjectHelper.hh new file mode 100644 index 0000000..a929563 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFFormFieldObjectHelper.hh @@ -0,0 +1,195 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFORMFIELDOBJECTHELPER_HH +#define QPDFFORMFIELDOBJECTHELPER_HH + +#include + +#include +#include + +class QPDFAnnotationObjectHelper; + +// This object helper helps with form fields for interactive forms. Please see comments in +// QPDFAcroFormDocumentHelper.hh for additional details. +class QPDFFormFieldObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFormFieldObjectHelper(); + QPDF_DLL + QPDFFormFieldObjectHelper(QPDFObjectHandle); + + ~QPDFFormFieldObjectHelper() override = default; + + QPDF_DLL + bool isNull(); + + // Return the field's parent. A form field object helper whose underlying object is null is + // returned if there is no parent. This condition may be tested by calling isNull(). + QPDF_DLL + QPDFFormFieldObjectHelper getParent(); + + // Return the top-level field for this field. Typically this will be the field itself or its + // parent. If is_different is provided, it is set to true if the top-level field is different + // from the field itself; otherwise it is set to false. + QPDF_DLL + QPDFFormFieldObjectHelper getTopLevelField(bool* is_different = nullptr); + + // Get a field value, possibly inheriting the value from an ancestor node. + QPDF_DLL + QPDFObjectHandle getInheritableFieldValue(std::string const& name); + + // Get an inherited field value as a string. If it is not a string, silently return the empty + // string. + QPDF_DLL + std::string getInheritableFieldValueAsString(std::string const& name); + + // Get an inherited field value of type name as a string representing the name. If it is not a + // name, silently return the empty string. + QPDF_DLL + std::string getInheritableFieldValueAsName(std::string const& name); + + // Returns the value of /FT if present, otherwise returns the empty string. + QPDF_DLL + std::string getFieldType(); + + QPDF_DLL + std::string getFullyQualifiedName(); + + QPDF_DLL + std::string getPartialName(); + + // Return the alternative field name (/TU), which is the field name intended to be presented to + // users. If not present, fall back to the fully qualified name. + QPDF_DLL + std::string getAlternativeName(); + + // Return the mapping field name (/TM). If not present, fall back to the alternative name, then + // to the partial name. + QPDF_DLL + std::string getMappingName(); + + QPDF_DLL + QPDFObjectHandle getValue(); + + // Return the field's value as a string. If this is called with a field whose value is not a + // string, the empty string will be silently returned. + QPDF_DLL + std::string getValueAsString(); + + QPDF_DLL + QPDFObjectHandle getDefaultValue(); + + // Return the field's default value as a string. If this is called with a field whose value is + // not a string, the empty string will be silently returned. + QPDF_DLL + std::string getDefaultValueAsString(); + + // Return the default appearance string, taking inheritance from the field tree into account. + // Returns the empty string if the default appearance string is not available (because it's + // erroneously absent or because this is not a variable text field). If not found in the field + // hierarchy, look in /AcroForm. + QPDF_DLL + std::string getDefaultAppearance(); + + // Return the default resource dictionary for the field. This comes not from the field but from + // the document-level /AcroForm dictionary. While several PDF generators put a /DR key in the + // form field's dictionary, experimentation suggests that many popular readers, including Adobe + // Acrobat and Acrobat Reader, ignore any /DR item on the field. + QPDF_DLL + QPDFObjectHandle getDefaultResources(); + + // Return the quadding value, taking inheritance from the field tree into account. Returns 0 if + // quadding is not specified. Look in /AcroForm if not found in the field hierarchy. + QPDF_DLL + int getQuadding(); + + // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as defined in + // qpdf/Constants.h + QPDF_DLL + int getFlags(); + + // Methods for testing for particular types of form fields + + // Returns true if field is of type /Tx + QPDF_DLL + bool isText(); + // Returns true if field is of type /Btn and flags do not indicate some other type of button. + QPDF_DLL + bool isCheckbox(); + // Returns true if field is a checkbox and is checked. + QPDF_DLL + bool isChecked(); + // Returns true if field is of type /Btn and flags indicate that it is a radio button + QPDF_DLL + bool isRadioButton(); + // Returns true if field is of type /Btn and flags indicate that it is a pushbutton + QPDF_DLL + bool isPushbutton(); + // Returns true if field is of type /Ch + QPDF_DLL + bool isChoice(); + // Returns choices display values as UTF-8 strings + QPDF_DLL + std::vector getChoices(); + + // Set an attribute to the given value. If you have a QPDFAcroFormDocumentHelper and you want to + // set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, QPDFObjectHandle value); + + // Set an attribute to the given value as a Unicode string (UTF-16 BE encoded). The input string + // should be UTF-8 encoded. If you have a QPDFAcroFormDocumentHelper and you want to set the + // name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, std::string const& utf8_value); + + // Set /V (field value) to the given value. If need_appearances is true and the field type is + // either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this + // method not to set /NeedAppearances if you are going to generate an appearance stream + // yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes, + // radio buttons, pushbuttons) specially. When setting a checkbox value, any value other than + // /Off will be treated as on, and the actual value set will be based on the appearance stream's + // /N dictionary, so the value that ends up in /V may not exactly match the value you pass in. + QPDF_DLL + void setV(QPDFObjectHandle value, bool need_appearances = true); + + // Set /V (field value) to the given string value encoded as a Unicode string. The input value + // should be UTF-8 encoded. See comments above about /NeedAppearances. + QPDF_DLL + void setV(std::string const& utf8_value, bool need_appearances = true); + + // Update the appearance stream for this field. Note that qpdf's ability to generate appearance + // streams is limited. We only generate appearance streams for streams of type text or choice. + // The appearance uses the default parameters provided in the file, and it only supports ASCII + // characters. Quadding is currently ignored. While this functionality is limited, it should do + // a decent job on properly constructed PDF files when field values are restricted to ASCII + // characters. + QPDF_DLL + void generateAppearance(QPDFAnnotationObjectHelper&); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFFORMFIELDOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFJob.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFJob.hh new file mode 100644 index 0000000..cace443 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFJob.hh @@ -0,0 +1,542 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFJOB_HH +#define QPDFJOB_HH + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFWriter; +class Pipeline; +class QPDFLogger; + +class QPDFJob +{ + public: + static int constexpr LATEST_JOB_JSON = 1; + + // Exit codes -- returned by getExitCode() after calling run() + static int constexpr EXIT_ERROR = qpdf_exit_error; + static int constexpr EXIT_WARNING = qpdf_exit_warning; + // For is-encrypted and requires-password + static int constexpr EXIT_IS_NOT_ENCRYPTED = qpdf_exit_is_not_encrypted; + static int constexpr EXIT_CORRECT_PASSWORD = qpdf_exit_correct_password; + + // QPDFUsage is thrown if there are any usage-like errors when calling Config methods. + QPDF_DLL + QPDFJob(); + + // SETUP FUNCTIONS + + // Initialize a QPDFJob object from argv, which must be a null-terminated array of + // null-terminated UTF-8-encoded C strings. The progname_env argument is the name of an + // environment variable which, if set, overrides the name of the executable for purposes of + // generating the --completion options. See QPDFArgParser for details. If a null pointer is + // passed in, the default value of "QPDF_EXECUTABLE" is used. This is used by the QPDF cli, + // which just initializes a QPDFJob from argv, calls run(), and handles errors and exit status + // issues. You can perform much of the cli functionality programmatically in this way rather + // than using the regular API. This is exposed in the C API, which makes it easier to get + // certain high-level qpdf functionality from other languages. If there are any command-line + // errors, this method will throw QPDFUsage which is derived from std::runtime_error. Other + // exceptions may be thrown in some cases. Note that argc, and argv should be UTF-8 encoded. If + // you are calling this from a Windows Unicode-aware main (wmain), see + // QUtil::call_main_from_wmain for information about converting arguments to UTF-8. This method + // will mutate arguments that are passed to it. + QPDF_DLL + void initializeFromArgv(char const* const argv[], char const* progname_env = nullptr); + + // Initialize a QPDFJob from json. Passing partial = true prevents this method from doing the + // final checks (calling checkConfiguration) after processing the json file. This makes it + // possible to initialize QPDFJob in stages using multiple json files or to have a json file + // that can be processed from the CLI with --job-json-file and be combined with other arguments. + // For example, you might include only encryption parameters, leaving it up to the rest of the + // command-line arguments to provide input and output files. initializeFromJson is called with + // partial = true when invoked from the command line. To make sure that the json file is fully + // valid on its own, just don't specify any other command-line flags. If there are any + // configuration errors, QPDFUsage is thrown. Some error messages may be CLI-centric. If an + // exception tells you to use the "--some-option" option, set the "someOption" key in the JSON + // object instead. + QPDF_DLL + void initializeFromJson(std::string const& json, bool partial = false); + + // Set name that is used to prefix verbose messages, progress messages, and other things that + // the library writes to output and error streams on the caller's behalf. Defaults to "qpdf". + QPDF_DLL + void setMessagePrefix(std::string const&); + QPDF_DLL + std::string getMessagePrefix() const; + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // If you set a custom logger here, the logger will be passed to all subsequent QPDF objects + // created by this QPDFJob object. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // You can register a custom progress reporter to be called by QPDFWriter (see + // QPDFWriter::registerProgressReporter). This is only called if you also request progress + // reporting through normal configuration methods (e.g., pass --progress, call + // config()->progress, etc.) + QPDF_DLL + void registerProgressReporter(std::function); + + // Check to make sure no contradictory options have been specified. This is called automatically + // after initializing from argv or json and is also called by run, but you can call it manually + // as well. It throws a QPDFUsage exception if there are any errors. This Config object (see + // CONFIGURATION) also has a checkConfiguration method which calls this one. + QPDF_DLL + void checkConfiguration(); + + // Returns true if output is created by the specified job. + QPDF_DLL + bool createsOutput() const; + + // SEE BELOW FOR MORE PUBLIC METHODS AND CLASSES + private: + // These structures are private but we need to define them before the public Config classes. + struct CopyAttachmentFrom + { + std::string path; + std::string password; + std::string prefix; + }; + + struct AddAttachment + { + std::string path; + std::string key; + std::string filename; + std::string creationdate; + std::string moddate; + std::string mimetype; + std::string description; + bool replace{false}; + }; + + public: + // CONFIGURATION + + // Configuration classes are implemented in QPDFJob_config.cc. + + // The config() method returns a shared pointer to a Config object. The Config object contains + // methods that correspond with qpdf command-line arguments. You can use a fluent interface to + // configure a QPDFJob object that would do exactly the same thing as a specific qpdf command. + // The example qpdf-job.cc contains an example of this usage. You can also use + // initializeFromJson or initializeFromArgv to initialize a QPDFJob object. + + // Notes about the Config methods: + // + // * Most of the method declarations are automatically generated in header files that are + // included within the class definitions. They correspond in predictable ways to the + // command-line arguments and are generated from the same code that generates the command-line + // argument parsing code. + // + // * Methods return pointers, rather than references, to configuration objects. References + // might feel more familiar to users of fluent interfaces, so why do we use pointers? The + // main methods that create them return smart pointers so that users can initialize them when + // needed, which you can't do with references. Returning pointers instead of references makes + // for a more uniform interface. + + // Maintainer documentation: see the section in README-maintainer called "HOW TO ADD A + // COMMAND-LINE ARGUMENT", which contains references to additional places in the documentation. + + class Config; + + class AttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endAddAttachment(); + QPDF_DLL + AttConfig* file(std::string const& parameter); + +#include + + private: + AttConfig(Config*); + AttConfig(AttConfig const&) = delete; + + Config* config; + AddAttachment att; + }; + + class CopyAttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endCopyAttachmentsFrom(); + QPDF_DLL + CopyAttConfig* file(std::string const& parameter); + +#include + + private: + CopyAttConfig(Config*); + CopyAttConfig(CopyAttConfig const&) = delete; + + Config* config; + CopyAttachmentFrom caf; + }; + + class PagesConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endPages(); + // From qpdf 11.9.0, you can call file(), range(), and password(). Each call to file() + // starts a new page spec. + QPDF_DLL + PagesConfig* pageSpec( + std::string const& filename, std::string const& range, char const* password = nullptr); + +#include + + private: + PagesConfig(Config*); + PagesConfig(PagesConfig const&) = delete; + + Config* config; + }; + + class UOConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endUnderlayOverlay(); + +#include + + private: + UOConfig(Config*); + UOConfig(UOConfig const&) = delete; + + Config* config; + }; + + class EncConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endEncrypt(); + QPDF_DLL + EncConfig* file(std::string const& parameter); + +#include + + private: + EncConfig(Config*); + EncConfig(EncConfig const&) = delete; + + Config* config; + }; + + class PageLabelsConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endSetPageLabels(); + +#include + + private: + PageLabelsConfig(Config*); + PageLabelsConfig(PageLabelsConfig const&) = delete; + + Config* config; + }; + + class GlobalConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endGlobal(); + +#include + + GlobalConfig(Config*); // for qpdf internal use only + GlobalConfig(GlobalConfig const&) = delete; + + private: + Config* config; + }; + + class Config + { + friend class QPDFJob; + + public: + // Proxy to QPDFJob::checkConfiguration() + QPDF_DLL + void checkConfiguration(); + + QPDF_DLL + Config* inputFile(std::string const& filename); + QPDF_DLL + Config* emptyInput(); + QPDF_DLL + Config* outputFile(std::string const& filename); + QPDF_DLL + Config* replaceInput(); + QPDF_DLL + Config* setPageLabels(std::vector const& specs); + + QPDF_DLL + std::shared_ptr copyAttachmentsFrom(); + QPDF_DLL + std::shared_ptr addAttachment(); + QPDF_DLL + std::shared_ptr global(); + QPDF_DLL + std::shared_ptr pages(); + QPDF_DLL + std::shared_ptr overlay(); + QPDF_DLL + std::shared_ptr underlay(); + QPDF_DLL + std::shared_ptr + encrypt(int keylen, std::string const& user_password, std::string const& owner_password); + +#include + + private: + Config() = delete; + Config(Config const&) = delete; + Config(QPDFJob& job) : + o(job) + { + } + QPDFJob& o; + }; + + // Return a top-level configuration item. See CONFIGURATION above for details. If an invalid + // configuration is created (such as supplying contradictory options, omitting an input file, + // etc.), QPDFUsage is thrown. Note that error messages are CLI-centric, but you can map them + // into config calls. For example, if an exception tells you to use the --some-option flag, you + // should call config()->someOption() instead. + QPDF_DLL + std::shared_ptr config(); + + // Execute the job + QPDF_DLL + void run(); + + // The following two methods allow a job to be run in two stages - creation of a QPDF object and + // writing of the QPDF object. This allows the QPDF object to be modified prior to writing it + // out. See examples/qpdfjob-remove-annotations for an illustration of its use. + + // Run the first stage of the job. Return a nullptr if the configuration is not valid. + QPDF_DLL + std::unique_ptr createQPDF(); + + // Run the second stage of the job. Do nothing if a nullptr is passed as parameter. + QPDF_DLL + void writeQPDF(QPDF& qpdf); + + // CHECK STATUS -- these methods provide information known after run() is called. + + QPDF_DLL + bool hasWarnings() const; + + // Return one of the EXIT_* constants defined at the top of the class declaration. This may be + // called after run() when run() did not throw an exception. Takes into consideration whether + // isEncrypted or requiresPassword was called. Note that this function does not know whether + // run() threw an exception, so code that uses this to determine how to exit should explicitly + // use EXIT_ERROR if run() threw an exception. + QPDF_DLL + int getExitCode() const; + + // Return value is bitwise OR of values from qpdf_encryption_status_e + QPDF_DLL + unsigned long getEncryptionStatus(); + + // HELPER FUNCTIONS -- methods useful for calling in handlers that interact with QPDFJob during + // run or initialization. + + // If in verbose mode, call the given function, passing in the output stream and message prefix. + QPDF_DLL + void doIfVerbose(std::function fn); + + // Provide a string that is the help information ("schema" for the qpdf-specific JSON object) + // for the specified version of JSON output. + QPDF_DLL + static std::string json_out_schema(int version); + + [[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL json_out_schema_v1(); + + // Provide a string that is the help information for specified version of JSON format for + // QPDFJob. + QPDF_DLL + static std::string job_json_schema(int version); + + [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1(); + + private: + struct PageNo; + struct Selection; + struct Input; + struct Inputs; + struct RotationSpec; + struct UnderOverlay; + struct PageLabelSpec; + + enum password_mode_e { pm_bytes, pm_hex_bytes, pm_unicode, pm_auto }; + + // Helper functions + static void usage(std::string const& msg); + static JSON json_schema(int json_version, std::set* keys = nullptr); + static void parse_object_id(std::string const& objspec, bool& trailer, int& obj, int& gen); + void parseRotationParameter(std::string const&); + std::vector parseNumrange(char const* range, int max); + + // Basic file processing + void processFile( + std::unique_ptr&, + char const* filename, + char const* password, + bool used_for_input, + bool main_input); + void processInputSource( + std::unique_ptr&, + std::shared_ptr is, + char const* password, + bool used_for_input); + void doProcess( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + void doProcessOnce( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + + // Transformations + void handlePageSpecs(QPDF& pdf); + bool shouldRemoveUnreferencedResources(QPDF& pdf); + void handleRotations(QPDF& pdf); + void getUOPagenos( + std::vector& uo, std::vector>>& pagenos); + void handleUnderOverlay(QPDF& pdf); + std::string doUnderOverlayForPage( + QPDF& pdf, + UnderOverlay& uo, + std::vector>>& pagenos, + PageNo const& page_idx, + size_t uo_idx, + std::map>& fo, + QPDFPageObjectHelper& dest_page); + void validateUnderOverlay(QPDF& pdf, UnderOverlay* uo); + void handleTransformations(QPDF& pdf); + void addAttachments(QPDF& pdf); + void copyAttachments(QPDF& pdf); + + // Inspection + void doInspection(QPDF& pdf); + void doCheck(QPDF& pdf); + void showEncryption(QPDF& pdf); + void doShowObj(QPDF& pdf); + void doShowPages(QPDF& pdf); + void doListAttachments(QPDF& pdf); + void doShowAttachment(QPDF& pdf); + + // Output generation + void doSplitPages(QPDF& pdf); + void setWriterOptions(qpdf::Writer&); + void setEncryptionOptions(QPDFWriter&); + void maybeFixWritePassword(int R, std::string& password); + void writeOutfile(QPDF& pdf); + void writeJSON(QPDF& pdf); + + // JSON + void doJSON(QPDF& pdf, Pipeline*); + QPDFObjGen::set getWantedJSONObjects(); + void doJSONObjects(Pipeline* p, bool& first, QPDF& pdf); + void doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPages(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPageLabels(Pipeline* p, bool& first, QPDF& pdf); + void doJSONOutlines(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAcroform(Pipeline* p, bool& first, QPDF& pdf); + void doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf); + void addOutlinesToJson( + std::vector outlines, + JSON& j, + std::map& page_numbers); + + enum remove_unref_e { re_auto, re_yes, re_no }; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOBJECT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFLogger.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFLogger.hh new file mode 100644 index 0000000..1e360be --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFLogger.hh @@ -0,0 +1,164 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFLOGGER_HH +#define QPDFLOGGER_HH + +#include +#include +#include +#include + +class QPDFLogger +{ + public: + QPDF_DLL + static std::shared_ptr create(); + + // Return the default logger. In general, you should use the default logger. You can also create + // your own loggers and use them with QPDF and QPDFJob objects, but there are few reasons to do + // so. One reason may be that you are using multiple QPDF or QPDFJob objects in different + // threads and want to capture output and errors to different streams. (Note that a single QPDF + // or QPDFJob can't be safely used from multiple threads, but it is safe to use separate QPDF + // and QPDFJob objects on separate threads.) Another possible reason would be if you are writing + // an application that uses the qpdf library directly and qpdf is also used by a downstream + // library or if you are using qpdf from a library and don't want to interfere with potential + // uses of qpdf by other libraries or applications. + QPDF_DLL + static std::shared_ptr defaultLogger(); + + // Defaults: + // + // info -- if save is standard output, standard error, else standard output + // warn -- whatever error points to + // error -- standard error + // save -- undefined unless set + // + // "info" is used for diagnostic messages, verbose messages, and progress messages. "warn" is + // used for warnings. "error" is used for errors. "save" is used for saving output -- see below. + // + // On deletion, finish() is called for the standard output and standard error pipelines, which + // flushes output. If you supply any custom pipelines, you must call finish() on them yourself. + // Note that calling finish is not needed for string, stdio, or ostream pipelines. + // + // NOTES ABOUT THE SAVE PIPELINE + // + // The save pipeline is used by QPDFJob when some kind of binary output is being saved. This + // includes saving attachments and stream data and also includes when the output file is + // standard output. If you want to grab that output, you can call setSave. See + // examples/qpdfjob-save-attachment.cc and examples/qpdfjob-c-save-attachment.c. + // + // You should never set the save pipeline to the same destination as something else. Doing so + // will corrupt your save output. If you want to save to standard output, use the method + // saveToStandardOutput(). In addition to setting the save pipeline, that does the following + // extra things: + // + // * If standard output has been used, a logic error is thrown + // * If info is set to standard output at the time of the set save call, it is switched to + // standard error. + // + // This is not a guarantee. You can still mess this up in ways that are not checked. Here are a + // few examples: + // + // * Don't set any pipeline to standard output *after* passing it to setSave() + // * Don't use a separate mechanism to write stdout/stderr other than + // QPDFLogger::standardOutput() + // * Don't set anything to the same custom pipeline that save is set to. + // + // Just be sure that if you change pipelines around, you should avoid having the save pipeline + // also be used for any other purpose. The special case for saving to standard output allows you + // to call saveToStandardOutput() early without having to worry about the info pipeline. + + QPDF_DLL + void info(char const*); + QPDF_DLL + void info(std::string const&); + QPDF_DLL + std::shared_ptr getInfo(bool null_okay = false); + + QPDF_DLL + void warn(char const*); + QPDF_DLL + void warn(std::string const&); + QPDF_DLL + std::shared_ptr getWarn(bool null_okay = false); + + QPDF_DLL + void error(char const*); + QPDF_DLL + void error(std::string const&); + QPDF_DLL + std::shared_ptr getError(bool null_okay = false); + + QPDF_DLL + std::shared_ptr getSave(bool null_okay = false); + + QPDF_DLL + std::shared_ptr standardOutput(); + QPDF_DLL + std::shared_ptr standardError(); + QPDF_DLL + std::shared_ptr discard(); + + // Passing a null pointer resets to default + QPDF_DLL + void setInfo(std::shared_ptr); + QPDF_DLL + void setWarn(std::shared_ptr); + QPDF_DLL + void setError(std::shared_ptr); + // See notes above about the save pipeline + QPDF_DLL + void setSave(std::shared_ptr, bool only_if_not_set); + QPDF_DLL + void saveToStandardOutput(bool only_if_not_set); + + // Shortcut for logic to reset output to new output/error streams. out_stream is used for info, + // err_stream is used for error, and warning is cleared so that it follows error. + QPDF_DLL + void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + private: + QPDFLogger(); + std::shared_ptr throwIfNull(std::shared_ptr, bool null_okay); + + class Members + { + friend class QPDFLogger; + + public: + ~Members(); + + private: + Members(); + Members(Members const&) = delete; + + std::shared_ptr p_discard; + std::shared_ptr p_real_stdout; + std::shared_ptr p_stdout; + std::shared_ptr p_stderr; + std::shared_ptr p_info; + std::shared_ptr p_warn; + std::shared_ptr p_error; + std::shared_ptr p_save; + }; + std::shared_ptr m; +}; + +#endif // QPDFLOGGER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFMatrix.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFMatrix.hh new file mode 100644 index 0000000..37624df --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFMatrix.hh @@ -0,0 +1,93 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFMATRIX_HH +#define QPDFMATRIX_HH + +#include +#include +#include + +// This class represents a PDF transformation matrix using a tuple such that +// +// ┌ ┐ +// │ a b 0 │ +// (a, b, c, d, e, f) = │ c d 0 │ +// │ e f 1 │ +// └ ┘ +class QPDFMatrix +{ + public: + QPDF_DLL + QPDFMatrix(); + QPDF_DLL + QPDFMatrix(double a, double b, double c, double d, double e, double f); + QPDF_DLL + QPDFMatrix(QPDFObjectHandle::Matrix const&); + + // Returns the six values separated by spaces as real numbers with trimmed zeroes. + QPDF_DLL + std::string unparse() const; + + QPDF_DLL + QPDFObjectHandle::Matrix getAsMatrix() const; + + // Replace this with other * this + QPDF_DLL + void concat(QPDFMatrix const& other); + + // Same as concat(sx, 0, 0, sy, 0, 0) + QPDF_DLL + void scale(double sx, double sy); + + // Same as concat(1, 0, 0, 1, tx, ty); + QPDF_DLL + void translate(double tx, double ty); + + // Any value other than 90, 180, or 270 is ignored + QPDF_DLL + void rotatex90(int angle); + + // Transform a point. The underlying operation is to take + // [x y 1] * this + // and take the first and second rows of the result as xp and yp. + QPDF_DLL + void transform(double x, double y, double& xp, double& yp) const; + + // Transform a rectangle by creating a new rectangle that tightly bounds the polygon resulting + // from transforming the four corners. + QPDF_DLL + QPDFObjectHandle::Rectangle transformRectangle(QPDFObjectHandle::Rectangle r) const; + + // operator== tests for exact equality, not considering deltas for floating point. + QPDF_DLL + bool operator==(QPDFMatrix const& rhs) const; + + QPDF_DLL + bool operator!=(QPDFMatrix const& rhs) const; + + double a; + double b; + double c; + double d; + double e; + double f; +}; + +#endif // QPDFMATRIX_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFNameTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFNameTreeObjectHelper.hh new file mode 100644 index 0000000..7677819 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFNameTreeObjectHelper.hh @@ -0,0 +1,184 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNAMETREEOBJECTHELPER_HH +#define QPDFNAMETREEOBJECTHELPER_HH + +#include +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for name trees. See section 7.9.6 in the PDF spec (ISO 32000) for a +// description of name trees. When looking up items in the name tree, use UTF-8 strings. All names +// are normalized for lookup purposes. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNameTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNameTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Create an empty name tree + QPDF_DLL + static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + QPDF_DLL + ~QPDFNameTreeObjectHelper() override; + + // Return whether the name tree has an explicit entry for this name. + QPDF_DLL + bool hasName(std::string const& utf8); + + // Find an object by name. If found, returns true and initializes oh. See also find(). + QPDF_DLL + bool findObject(std::string const& utf8, QPDFObjectHandle& oh); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNameTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(std::string const& key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a string and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(std::string const& key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(std::string const& key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(std::string const& key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the name tree as a map. Note that name trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNameTreeObjectHelper's iterator. + QPDF_DLL + std::map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNAMETREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFNumberTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFNumberTreeObjectHelper.hh new file mode 100644 index 0000000..b7d7716 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFNumberTreeObjectHelper.hh @@ -0,0 +1,200 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNUMBERTREEOBJECTHELPER_HH +#define QPDFNUMBERTREEOBJECTHELPER_HH + +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for number trees. See section 7.9.7 in the PDF spec (ISO 32000) for a +// description of number trees. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNumberTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNumberTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + QPDF_DLL + ~QPDFNumberTreeObjectHelper() override; + + // Create an empty number tree + QPDF_DLL + static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + typedef long long int numtree_number; + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Return overall minimum and maximum indices + QPDF_DLL + numtree_number getMin(); + QPDF_DLL + numtree_number getMax(); + + // Return whether the number tree has an explicit entry for this number. + QPDF_DLL + bool hasIndex(numtree_number idx); + + // Find an object with a specific index. If found, returns true and initializes oh. See also + // find(). + QPDF_DLL + bool findObject(numtree_number idx, QPDFObjectHandle& oh); + // Find the object at the index or, if not found, the object whose index is the highest index + // less than the requested index. If the requested index is less than the minimum, return false. + // Otherwise, return true, initialize oh to the object, and set offset to the difference between + // the requested index and the actual index. For example, if a number tree has values for 3 and + // 6 and idx is 5, this method would return true, initialize oh to the value with index 3, and + // set offset to 2 (5 - 3). See also find(). + QPDF_DLL + bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNumberTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(numtree_number key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a numtree_number and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(numtree_number key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(numtree_number key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(numtree_number key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the number tree as a map. Note that number trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNumberTreeObjectHelper's iterator. + typedef std::map idx_map; + QPDF_DLL + idx_map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNUMBERTREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjGen.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjGen.hh new file mode 100644 index 0000000..1f92488 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjGen.hh @@ -0,0 +1,137 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJGEN_HH +#define QPDFOBJGEN_HH + +#include + +#include +#include +#include + +class QPDFObjectHandle; +class QPDFObjectHelper; + +// This class represents an object ID and generation pair. It is suitable to use as a key in a map +// or set. + +class QPDFObjGen +{ + public: + QPDFObjGen() = default; + QPDFObjGen(int obj, int gen) : + obj(obj), + gen(gen) + { + } + bool + operator<(QPDFObjGen const& rhs) const + { + return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen); + } + bool + operator==(QPDFObjGen const& rhs) const + { + return obj == rhs.obj && gen == rhs.gen; + } + bool + operator!=(QPDFObjGen const& rhs) const + { + return !(*this == rhs); + } + int + getObj() const + { + return obj; + } + int + getGen() const + { + return gen; + } + bool + isIndirect() const + { + return obj != 0; + } + std::string + unparse(char separator = ',') const + { + return std::to_string(obj) + separator + std::to_string(gen); + } + friend std::ostream& + operator<<(std::ostream& os, QPDFObjGen og) + { + os << og.obj << "," << og.gen; + return os; + } + + // Convenience class for loop detection when processing objects. + // + // The class adds 'add' methods to a std::set which allows to test whether an + // QPDFObjGen is present in the set and to insert it in a single operation. The 'add' method is + // overloaded to take a QPDFObjGen, QPDFObjectHandle or an QPDFObjectHelper as parameter. + // + // The erase method is modified to ignore requests to erase QPDFObjGen(0, 0). + // + // Usage example: + // + // void process_object(QPDFObjectHandle oh, QPDFObjGen::set& seen) + // { + // if (seen.add(oh)) { + // // handle first encounter of oh + // } else { + // // handle loop / subsequent encounter of oh + // } + // } + class QPDF_DLL_CLASS set: public std::set + { + public: + // Add 'og' to the set. Return false if 'og' is already present in the set. Attempts to + // insert QPDFObjGen(0, 0) are ignored. + bool + add(QPDFObjGen og) + { + if (og.isIndirect()) { + if (count(og)) { + return false; + } + emplace(og); + } + return true; + } + + void + erase(QPDFObjGen og) + { + if (og.isIndirect()) { + std::set::erase(og); + } + } + }; + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created and destroyed. + int obj{0}; + int gen{0}; +}; + +#endif // QPDFOBJGEN_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObject.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObject.hh new file mode 100644 index 0000000..8499637 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObject.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECT_OLD_HH +#define QPDFOBJECT_OLD_HH + +// Current code should not include . This file exists +// to ensure that code that includes it doesn't accidentally work because +// of an old qpdf installed on the system. Including this file became an +// error with qpdf version 12. The internal QPDFObject API is defined in +// QPDFObject_private.hh, which is not part of the public API. + +// Instead of including this header, include , and +// replace `QPDFObject::ot_` with `::ot_` in your code. +#error "QPDFObject.hh is obsolete; see comments in QPDFObject.hh for details" + +#endif // QPDFOBJECT_OLD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjectHandle.hh new file mode 100644 index 0000000..9fef4e6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjectHandle.hh @@ -0,0 +1,1576 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECTHANDLE_HH +#define QPDFOBJECTHANDLE_HH + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class Pipeline; +class QPDF_Array; +class QPDF_Bool; +class QPDF_Dictionary; +class QPDF_InlineImage; +class QPDF_Integer; +class QPDF_Name; +class QPDF_Null; +class QPDF_Operator; +class QPDF_Real; +class QPDF_Reserved; +class QPDF_Stream; +class QPDF_String; +class QPDFObject; +class QPDFObjectHandle; +class QPDFTokenizer; +class QPDFExc; +class Pl_QPDFTokenizer; +class QPDFMatrix; +namespace qpdf::impl +{ + class Parser; +} + +class QPDFObjectHandle: public qpdf::BaseHandle +{ + friend class qpdf::impl::Parser; + + public: + // This class is used by replaceStreamData. It provides an alternative way of associating + // stream data with a stream. See comments on replaceStreamData and newStream for additional + // details. + class QPDF_DLL_CLASS StreamDataProvider + { + public: + QPDF_DLL + StreamDataProvider(bool supports_retry = false); + + QPDF_DLL + virtual ~StreamDataProvider(); + // The implementation of this function must write stream data to the given pipeline. The + // stream data must conform to whatever filters are explicitly associated with the stream. + // QPDFWriter may, in some cases, add compression, but if it does, it will update the + // filters as needed. Every call to provideStreamData for a given stream must write the same + // data. Note that, when writing linearized files, qpdf will call your provideStreamData + // twice, and if it generates different output, you risk generating invalid output or having + // qpdf throw an exception. The object ID and generation passed to this method are those + // that belong to the stream on behalf of which the provider is called. They may be ignored + // or used by the implementation for indexing or other purposes. This information is made + // available just to make it more convenient to use a single StreamDataProvider object to + // provide data for multiple streams. + + // A few things to keep in mind: + // + // * Stream data providers must not modify any objects since they may be called after some + // parts of the file have already been written. + // + // * Since qpdf may call provideStreamData multiple times when writing linearized files, if + // the work done by your stream data provider is slow or computationally intensive, you + // might want to implement your own cache. + // + // * Once you have called replaceStreamData, the original stream data is no longer directly + // accessible from the stream, but this is easy to work around by copying the stream to + // a separate QPDF object. The qpdf library implements this very efficiently without + // actually making a copy of the stream data. You can find examples of this pattern in + // some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc. + + // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or + // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by + // allowing an alternative provideStreamData to be implemented. You must implement at least + // one of the versions of provideStreamData below. If you implement the version that + // supports retry and returns a value, you should pass true as the value of supports_retry + // in the base class constructor. This will cause the library to call that version of the + // method, which should also return a boolean indicating whether it ran without errors. + QPDF_DLL + virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline); + QPDF_DLL + virtual bool provideStreamData( + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline); + QPDF_DLL virtual bool provideStreamData( + int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL + bool supportsRetry(); + + private: + bool supports_retry; + }; + + // The TokenFilter class provides a way to filter content streams in a lexically aware fashion. + // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter + // methods or can be applied on the spot by filterPageContents. You may also use + // Pl_QPDFTokenizer directly if you need full control. + // + // The handleToken method is called for each token, including the eof token, and then handleEOF + // is called at the very end. Handlers may call write (or writeToken) to pass data downstream. + // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of + // using TokenFilters. + // + // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you + // get the canonical, "parsed" representation of the token. For a string, this means that there + // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits) + // has been resolved. qpdf's internal representation of a name includes the leading slash. As + // such, you can't write the value of token.getValue() directly to output that is supposed to be + // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can + // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new + // string or name token from a canonical representation, use + // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or + // QPDFTokenizer::Token(QPDFTokenizer::tt_name, + // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can + // still write them with writeToken(). Example: + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain")) + // would write `/text#2fplain`, and + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`. + class QPDF_DLL_CLASS TokenFilter + { + public: + TokenFilter() = default; + virtual ~TokenFilter() = default; + virtual void handleToken(QPDFTokenizer::Token const&) = 0; + QPDF_DLL + virtual void handleEOF(); + + class PipelineAccessor + { + friend class Pl_QPDFTokenizer; + + private: + static void + setPipeline(TokenFilter* f, Pipeline* p) + { + f->setPipeline(p); + } + }; + + protected: + QPDF_DLL + void write(char const* data, size_t len); + QPDF_DLL + void write(std::string const& str); + QPDF_DLL + void writeToken(QPDFTokenizer::Token const&); + + private: + QPDF_DLL_PRIVATE + void setPipeline(Pipeline*); + + Pipeline* pipeline; + }; + + // This class is used by parse to decrypt strings when reading an object that contains encrypted + // strings. + class StringDecrypter + { + public: + virtual ~StringDecrypter() = default; + virtual void decryptString(std::string& val) = 0; + }; + + // This class is used by parsePageContents. Callers must instantiate a subclass of this with + // handlers defined to accept QPDFObjectHandles that are parsed from the stream. + class QPDF_DLL_CLASS ParserCallbacks + { + public: + virtual ~ParserCallbacks() = default; + // One of the handleObject methods must be overridden. + QPDF_DLL + virtual void handleObject(QPDFObjectHandle); + QPDF_DLL + virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length); + + virtual void handleEOF() = 0; + + // Override this if you want to know the full size of the contents, possibly after + // concatenation of multiple streams. This is called before the first call to handleObject. + QPDF_DLL + virtual void contentSize(size_t); + + protected: + // Implementors may call this method during parsing to terminate parsing early. This method + // throws an exception that is caught by parsePageContents, so its effect is immediate. + QPDF_DLL + void terminateParsing(); + }; + + // Convenience object for rectangles + class Rectangle + { + public: + Rectangle() : + llx(0.0), + lly(0.0), + urx(0.0), + ury(0.0) + { + } + Rectangle(double llx, double lly, double urx, double ury) : + llx(llx), + lly(lly), + urx(urx), + ury(ury) + { + } + + double llx; + double lly; + double urx; + double ury; + }; + + // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't + // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity + // transform matrix and this one is all zeroes. + class Matrix + { + public: + Matrix() : + a(0.0), + b(0.0), + c(0.0), + d(0.0), + e(0.0), + f(0.0) + { + } + Matrix(double a, double b, double c, double d, double e, double f) : + a(a), + b(b), + c(c), + d(d), + e(e), + f(f) + { + } + + double a; + double b; + double c; + double d; + double e; + double f; + }; + + QPDFObjectHandle() = default; + QPDFObjectHandle(QPDFObjectHandle const&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default; + QPDFObjectHandle(QPDFObjectHandle&&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default; + + // This method is provided for backward compatibility only. New code should convert to bool + // instead. + inline bool isInitialized() const; + + // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying + // object, meaning that changes to one are reflected in the other, or "if you paint one, the + // other one changes color." This does not perform a structural comparison of the contents of + // the objects. + QPDF_DLL + bool isSameObjectAs(QPDFObjectHandle const&) const; + + // Return type code and type name of underlying object. These are useful for doing rapid type + // tests (like switch statements) or for testing and debugging. + QPDF_DLL + qpdf_object_type_e getTypeCode() const; + QPDF_DLL + char const* getTypeName() const; + + // Exactly one of these will return true for any initialized object. Operator and InlineImage + // are only allowed in content streams. + QPDF_DLL + bool isBool() const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + bool isInteger() const; + QPDF_DLL + bool isReal() const; + QPDF_DLL + bool isName() const; + QPDF_DLL + bool isString() const; + QPDF_DLL + bool isOperator() const; + QPDF_DLL + bool isInlineImage() const; + QPDF_DLL + bool isArray() const; + QPDF_DLL + bool isDictionary() const; + QPDF_DLL + bool isStream() const; + QPDF_DLL + bool isReserved() const; + + // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended + // for internal use, but it can be used as an efficient way to check for nulls that are not + // indirect objects. + QPDF_DLL + bool isDirectNull() const; + + // This returns true in addition to the query for the specific type for indirect objects. + QPDF_DLL + bool isIndirect() const; + + // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse + // such an object will throw a logic_error. + QPDF_DLL + bool isDestroyed() const; + + // True for everything except array, dictionary, stream, word, and inline image. + QPDF_DLL + bool isScalar() const; + + // True if the object is a name object representing the provided name. + QPDF_DLL + bool isNameAndEquals(std::string const& name) const; + + // True if the object is a dictionary of the specified type and subtype, if any. + QPDF_DLL + bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const; + + // True if the object is a stream of the specified type and subtype, if any. + QPDF_DLL + bool isStreamOfType(std::string const& type, std::string const& subtype = "") const; + + // Public factory methods + + // Wrap an object in an array if it is not already an array. This is a helper for cases in which + // something in a PDF may either be a single item or an array of items, which is a common idiom. + QPDF_DLL + QPDFObjectHandle wrapInArray(); + + // Construct an object of any type from a string representation of the object. Throws QPDFExc + // with an empty filename and an offset into the string if there is an error. Any indirect + // object syntax (obj gen R) will cause a logic_error exception to be thrown. If + // object_description is provided, it will appear in the message of any QPDFExc exception thrown + // for invalid syntax. See also the global `operator ""_qpdf` defined below. + QPDF_DLL + static QPDFObjectHandle + parse(std::string const& object_str, std::string const& object_description = ""); + + // Construct an object of any type from a string representation of the object. Indirect object + // syntax (obj gen R) is allowed and will create indirect references within the passed-in + // context. If object_description is provided, it will appear in the message of any QPDFExc + // exception thrown for invalid syntax. Note that you can't parse an indirect object reference + // all by itself as parse will stop at the end of the first complete object, which will just be + // the first number and will report that there is trailing data at the end of the string. + QPDF_DLL + static QPDFObjectHandle + parse(QPDF* context, std::string const& object_str, std::string const& object_description = ""); + + // Construct an object as above by reading from the given InputSource at its current position + // and using the tokenizer you supply. Indirect objects and encrypted strings are permitted. + // This method was intended to be called by QPDF for parsing objects that are read from the + // object's input stream. To be removed in qpdf 13. See + // . + [[deprecated("to be removed in qpdf 13")]] QPDF_DLL static QPDFObjectHandle parse( + std::shared_ptr input, + std::string const& object_description, + QPDFTokenizer&, + bool& empty, + StringDecrypter* decrypter, + QPDF* context); + + // Return the offset where the object was found when parsed. A negative value means that the + // object was created without parsing. If the object is in a stream, the offset is from the + // beginning of the stream. Otherwise, the offset is from the beginning of the file. + QPDF_DLL + qpdf_offset_t getParsedOffset() const; + + // Older method: stream_or_array should be the value of /Contents from a page object. It's more + // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error + // messages will also be more useful because the page object information will be known. + QPDF_DLL + static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks); + + // When called on a stream or stream array that is some page's content streams, do the same as + // pipePageContents. This method is a lower level way to do what + // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a + // contents object that is disconnected from a page object. The description argument should + // describe the containing page and is used in error messages. The all_description argument is + // initialized to something that could be used to describe the result of the pipeline. It is the + // description amended with the identifiers of the underlying objects. Please note that if there + // is an array of content streams, p->finish() is called after each stream. If you pass a + // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an + // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the + // end. + QPDF_DLL + void + pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description); + + // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream + // data is passed through the token filter after all original filters but before content stream + // normalization if requested. This is a low-level interface to add it to a stream. You will + // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be + // applied to a page object, and which will automatically handle the case of pages whose + // contents are split across multiple streams. + QPDF_DLL + void addTokenFilter(std::shared_ptr token_filter); + + // Legacy helpers for parsing content streams. These methods are not going away, but newer code + // should call the correspond methods in QPDFPageObjectHelper instead. The specification and + // behavior of these methods are the same as the identically named methods in that class, but + // newer functionality will be added there. + QPDF_DLL + void parsePageContents(ParserCallbacks* callbacks); + QPDF_DLL + void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr); + // See comments for QPDFPageObjectHelper::pipeContents. + QPDF_DLL + void pipePageContents(Pipeline* p); + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + // End legacy content stream helpers + + // Called on a stream to filter the stream as if it were page contents. This can be used to + // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream. + QPDF_DLL + void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr); + // Called on a stream to parse the stream as page contents. This can be used to parse a form + // XObject. + QPDF_DLL + void parseAsContents(ParserCallbacks* callbacks); + + // Type-specific factories + QPDF_DLL + static QPDFObjectHandle newNull(); + QPDF_DLL + static QPDFObjectHandle newBool(bool value); + QPDF_DLL + static QPDFObjectHandle newInteger(long long value); + QPDF_DLL + static QPDFObjectHandle newReal(std::string const& value); + QPDF_DLL + static QPDFObjectHandle + newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true); + // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes, + // excluding the NUL character, and starting with a slash. Name objects as represented in the + // PDF specification can contain characters escaped with #, but such escaping is not of concern + // when calling QPDFObjectHandle methods not directly relating to parsing. For example, + // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return + // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse() + // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and + // modifying objects, you want to work with the internal, canonical representation. For names + // containing alphanumeric characters, dashes, and underscores, there is no difference between + // the two representations. For a lengthy discussion, see + // https://github.com/qpdf/qpdf/discussions/625. + QPDF_DLL + static QPDFObjectHandle newName(std::string const& name); + QPDF_DLL + static QPDFObjectHandle newString(std::string const& str); + // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in + // PDF files outside of content streams, such as in document metadata form field values, page + // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16 + // as needed to successfully encode all the characters. + QPDF_DLL + static QPDFObjectHandle newUnicodeString(std::string const& utf8_str); + QPDF_DLL + static QPDFObjectHandle newOperator(std::string const&); + QPDF_DLL + static QPDFObjectHandle newInlineImage(std::string const&); + QPDF_DLL + static QPDFObjectHandle newArray(); + QPDF_DLL + static QPDFObjectHandle newArray(std::vector const& items); + QPDF_DLL + static QPDFObjectHandle newArray(Rectangle const&); + QPDF_DLL + static QPDFObjectHandle newArray(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newArray(QPDFMatrix const&); + QPDF_DLL + static QPDFObjectHandle newDictionary(); + QPDF_DLL + static QPDFObjectHandle newDictionary(std::map const& items); + + // Create an array from a rectangle. Equivalent to the rectangle form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromRectangle(Rectangle const&); + // Create an array from a matrix. Equivalent to the matrix form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromMatrix(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newFromMatrix(QPDFMatrix const&); + + // Note: new stream creation methods have were added to the QPDF class starting with + // version 11.2.0. The ones in this class are here for backward compatibility. + + // Create a new stream and associate it with the given qpdf object. A subsequent call must be + // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be + // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively, + // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can + // call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf); + + // Create a new stream and associate it with the given qpdf object. Use the given buffer as the + // stream data. The stream dictionary's /Length key will automatically be set to the size of the + // data buffer. If additional keys are required, the stream's dictionary may be retrieved by + // calling getDict(), and the resulting dictionary may be modified. This method is just a + // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience + // methods for streams that require no parameters beyond the stream length. Note that you don't + // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will + // automatically compress uncompressed stream data. Example programs are provided that + // illustrate this. From QPDF 11.2, you can call QPDF::newStream() + // instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + // From QPDF 11.2, you can call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call + // QPDF::newReserved() instead. + QPDF_DLL + static QPDFObjectHandle newReserved(QPDF* qpdf); + + // Provide an owning qpdf and object description. The library does this automatically with + // objects that are read from the input PDF and with objects that are created programmatically + // and inserted into the QPDF as a new indirect object. Most end user code will not need to call + // this. If an object has an owning qpdf and object description, it enables qpdf to give + // warnings with proper context in some cases where it would otherwise raise exceptions. It is + // okay to add objects without an owning_qpdf to objects that have one, but it is an error to + // have a QPDF contain objects with owning_qpdf set to something else. To add objects from + // another qpdf, use copyForeignObject instead. + QPDF_DLL + void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description); + QPDF_DLL + bool hasObjectDescription() const; + + // Accessor methods + // + // (Note: this comment is referenced in qpdf-c.h and the manual.) + // + // In PDF files, objects have specific types, but there is nothing that prevents PDF files from + // containing objects of types that aren't expected by the specification. + // + // There are two flavors of accessor methods: + // + // * getSomethingValue() returns the value and issues a type warning if the type is incorrect. + // + // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns + // true and initializes a reference of the appropriate type. These methods never issue type + // warnings. + // + // The getSomethingValue() accessors and some of the other methods expect objects of a + // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as + // trying to get a dictionary key from an array, trying to get the string value of a number, + // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using + // the following behavior: + // + // * Requesting a value of the wrong type (int value from string, array item from a scalar or + // dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for + // number, the empty string for string, or the null object for an object handle. + // + // * Accessing an array item that is out of bounds will return a null object. + // + // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to + // a scalar or array) will be ignored. + // + // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5, + // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code + // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case + // for all objects whose origin was a PDF file), the warning is issued using the normal warning + // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them. + // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created + // programmatically), an exception will be thrown. + // + // The way to avoid getting any type warnings or exceptions, even when working with malformed + // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for + // example, make sure that isString() returns true before calling getStringValue()) and to + // always be sure that any array indices are in bounds. + // + // For additional discussion and rationale for this behavior, see the section in the QPDF manual + // entitled "Object Accessor Methods". + + // Methods for bool objects + QPDF_DLL + bool getBoolValue() const; + QPDF_DLL + bool getValueAsBool(bool&) const; + + // Methods for integer objects. Note: if an integer value is too big (too far away from zero in + // either direction) to fit in the requested return type, the maximum or minimum value for that + // return type may be returned. For example, on a system with 32-bit int, a numeric object with + // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX. + QPDF_DLL + long long getIntValue() const; + QPDF_DLL + bool getValueAsInt(long long&) const; + QPDF_DLL + int getIntValueAsInt() const; + QPDF_DLL + bool getValueAsInt(int&) const; + QPDF_DLL + unsigned long long getUIntValue() const; + QPDF_DLL + bool getValueAsUInt(unsigned long long&) const; + QPDF_DLL + unsigned int getUIntValueAsUInt() const; + QPDF_DLL + bool getValueAsUInt(unsigned int&) const; + + // Methods for real objects + QPDF_DLL + std::string getRealValue() const; + QPDF_DLL + bool getValueAsReal(std::string&) const; + + // Methods that work for both integer and real objects + QPDF_DLL + bool isNumber() const; + QPDF_DLL + double getNumericValue() const; + QPDF_DLL + bool getValueAsNumber(double&) const; + + // Methods for name objects. The returned name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + std::string getName() const; + QPDF_DLL + bool getValueAsName(std::string&) const; + + // Methods for string objects + QPDF_DLL + std::string getStringValue() const; + QPDF_DLL + bool getValueAsString(std::string&) const; + + // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise, + // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to + // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters + // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range + // unmapped. + QPDF_DLL + std::string getUTF8Value() const; + QPDF_DLL + bool getValueAsUTF8(std::string&) const; + + // Methods for content stream objects + QPDF_DLL + std::string getOperatorValue() const; + QPDF_DLL + bool getValueAsOperator(std::string&) const; + QPDF_DLL + std::string getInlineImageValue() const; + QPDF_DLL + bool getValueAsInlineImage(std::string&) const; + + // Methods for array objects; see also name and array objects. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.aitems()) + // { + // // iter is an array element + // } + class QPDFArrayItems; + QPDF_DLL + QPDFArrayItems aitems(); + + QPDF_DLL + int getArrayNItems() const; + QPDF_DLL + QPDFObjectHandle getArrayItem(int n) const; + // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling + // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of + // nulls. + QPDF_DLL + std::vector getArrayAsVector() const; + QPDF_DLL + bool isRectangle() const; + // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the + // rectangle [0, 0, 0, 0] + QPDF_DLL + Rectangle getArrayAsRectangle() const; + QPDF_DLL + bool isMatrix() const; + // If the array is an array of six numeric values, return as a matrix. Otherwise, return the + // matrix [1, 0, 0, 1, 0, 0] + QPDF_DLL + Matrix getArrayAsMatrix() const; + + // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as + // canonical name strings starting with a leading slash and not containing any PDF syntax + // escaping. See comments for getName() for details. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.ditems()) + // { + // // iter.first is the key + // // iter.second is the value + // } + class QPDFDictItems; + QPDF_DLL + QPDFDictItems ditems(); + + // Return true if key is present. Keys with null values are treated as if they are not present. + // This is as per the PDF spec. + QPDF_DLL + bool hasKey(std::string const&) const; + // Return the value for the key. If the key is not present, null is returned. + QPDF_DLL + QPDFObjectHandle getKey(std::string const&) const; + // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access + // lower-level dictionaries, as in + // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font"); + QPDF_DLL + QPDFObjectHandle getKeyIfDict(std::string const&) const; + // Return all keys. Keys with null values are treated as if they are not present. This is as + // per the PDF spec. + QPDF_DLL + std::set getKeys() const; + // Return dictionary as a map. Entries with null values are included. + QPDF_DLL + std::map getDictAsMap() const; + + // Methods for name and array objects. The name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + bool isOrHasName(std::string const&) const; + + // Make all resources in a resource dictionary indirect. This just goes through all entries of + // top-level subdictionaries and converts any direct objects to indirect objects. This can be + // useful to call before mergeResources if it is going to be called multiple times to prevent + // resources from being copied multiple times. + QPDF_DLL + void makeResourcesIndirect(QPDF& owning_qpdf); + + // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in + // dictionary subitems are resolved, and "conflicts" is initialized to a map such that + // conflicts[resource_type][old_key] == [new_key] + // + // See also makeResourcesIndirect, which can be useful to call before calling this. + // + // This method does nothing if both this object and the other object are not dictionaries. + // Otherwise, it has following behavior, where "object" refers to the object whose method is + // invoked, and "other" refers to the argument: + // + // * For each key in "other" whose value is an array: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, if "object" has an array in the same place, append to that array any objects + // in "other"'s array that are not already present. + // * For each key in "other" whose value is a dictionary: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, for each key in the subdictionary: + // * If key is not present in "object"'s entry, shallow copy it if direct or just add it if + // indirect. + // * Otherwise, if conflicts are being detected: + // * If there is a key (oldkey) already in the dictionary that points to the same indirect + // destination as key, indicate that key was replaced by oldkey. This would happen if + // these two resource dictionaries have previously been merged. + // * Otherwise pick a new key (newkey) that is unique within the resource dictionary, + // store that in the resource dictionary with key's destination as its destination, and + // indicate that key was replaced by newkey. + // + // The primary purpose of this method is to facilitate merging of resource dictionaries that are + // supposed to have the same scope as each other. For example, this can be used to merge a form + // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The + // "conflicts" parameter may be previously initialized. This method adds to whatever is already + // there, which can be useful when merging with multiple things. + QPDF_DLL + void mergeResources( + QPDFObjectHandle other, + std::map>* conflicts = nullptr); + + // Get all resource names from a resource dictionary. If this object is a dictionary, this + // method returns a set of all the keys in all top-level subdictionaries. For resources + // dictionaries, this is the collection of names that may be referenced in the content stream. + QPDF_DLL + std::set getResourceNames() const; + + // Find a unique name within a resource dictionary starting with a given prefix. This method + // works by appending a number to the given prefix. It searches starting with min_suffix and + // sets min_suffix to selected value upon return. This can be used to increase efficiency if + // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next + // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling + // this multiple times on the same resource dictionary, you can initialize resource_names by + // calling getResourceNames(), incrementally update it as you add resources, and keep passing it + // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time + // it's called. + QPDF_DLL + std::string getUniqueResourceName( + std::string const& prefix, + int& min_suffix, + std::set* resource_names = nullptr) const; + + // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF + // object. Indirect objects always have an owning QPDF. Direct objects that are read from the + // input source will also have an owning QPDF. Programmatically created objects will only have + // one if setObjectDescription was called. + // + // When the QPDF object that owns an object is destroyed, the object is changed into a null, and + // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the + // life of the QPDF. If in doubt, ask for it each time you need it. + + // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it + // returns a null pointer. Use this when you are able to handle the case of an object that + // doesn't have an owning QPDF. + QPDF_DLL + QPDF* getOwningQPDF() const; + // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a + // runtime_error. Use this when you know the object has to have an owning QPDF, such as when + // it's a known indirect object. Since streams are always indirect objects, this method can be + // used safely for streams. If error_msg is specified, it will be used at the contents of the + // runtime_error if there is now owner. + QPDF_DLL + QPDF& getQPDF(std::string const& error_msg = "") const; + + // Create a shallow copy of an object as a direct object, but do not traverse across indirect + // object boundaries. That means that, for dictionaries and arrays, any keys or items that were + // indirect objects will still be indirect objects that point to the same place. In the + // strictest sense, this is not a shallow copy because it recursively descends arrays and + // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You + // can't copy a stream this way. See copyStream() instead. + QPDF_DLL + QPDFObjectHandle shallowCopy(); + + // Create a true shallow copy of an array or dictionary, just copying the immediate items + // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in + // the copy, you are modifying the original, which is almost never what you want. However, if + // your intention is merely to *replace* top-level items or keys and not to modify lower-level + // items in the copy, this method is much faster than shallowCopy(). + QPDF_DLL + QPDFObjectHandle unsafeShallowCopy(); + + // Create a copy of this stream. The new stream and the old stream are independent: after the + // copy, either the original or the copy's dictionary or data can be modified without affecting + // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's + // data are made. If the source stream's data is already being provided by a StreamDataProvider, + // the new stream will use the same one, so you have to make sure your StreamDataProvider can + // handle that case. But if you're already using a StreamDataProvider, you probably don't need + // to call this method. + QPDF_DLL + QPDFObjectHandle copyStream(); + + // Mutator methods. + + // Since qpdf 11: for mutators that may add or remove an item, there are additional versions + // whose names contain "AndGet" that return the added or removed item. For example: + // + // auto new_dict = dict.replaceKeyAndGetNew( + // "/New", QPDFObjectHandle::newDictionary()); + // + // auto old_value = dict.replaceKeyAndGetOld( + // "/New", "(something)"_qpdf); + + // Recursively copy this object, making it direct. An exception is thrown if a loop is detected. + // With allow_streams true, keep indirect object references to streams. Otherwise, throw an + // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream + // is found, the resulting object is still associated with the containing qpdf. When + // allow_streams is false, the object will no longer be connected to the original QPDF object + // after this call completes successfully. + QPDF_DLL + void makeDirect(bool allow_streams = false); + + // Mutator methods for array objects + QPDF_DLL + void setArrayItem(int, QPDFObjectHandle const&); + QPDF_DLL + void setArrayFromVector(std::vector const& items); + // Insert an item before the item at the given position ("at") so that it has that position + // after insertion. If "at" is equal to the size of the array, insert the item at the end. + QPDF_DLL + void insertItem(int at, QPDFObjectHandle const& item); + // Like insertItem but return the item that was inserted. + QPDF_DLL + QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item); + // Append an item to an array. + QPDF_DLL + void appendItem(QPDFObjectHandle const& item); + // Append an item, and return the newly added item. + QPDF_DLL + QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item); + // Remove the item at that position, reducing the size of the array by one. + QPDF_DLL + void eraseItem(int at); + // Erase and item and return the item that was removed. + QPDF_DLL + QPDFObjectHandle eraseItemAndGetOld(int at); + + // Mutator methods for dictionary objects + + // Replace value of key, adding it if it does not exist. If value is null, remove the key. + QPDF_DLL + void replaceKey(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the value. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the old value, or null if the key was previously not present. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value); + // Remove key, doing nothing if key does not exist. + QPDF_DLL + void removeKey(std::string const& key); + // Remove key and return the old value. If the old value didn't exist, return a null object. + QPDF_DLL + QPDFObjectHandle removeKeyAndGetOld(std::string const& key); + + // Methods for stream objects + QPDF_DLL + QPDFObjectHandle getDict() const; + + // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode + // level, whether compression is enabled, and its ability to filter. Passing false will prevent + // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding + // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and + // recompressing a stream that it knows how to operate on for any application-specific reason, + // such as that you have already optimized its filtering. Note that this doesn't affect any + // other ways to get the stream's data, such as pipeStreamData or getStreamData. + QPDF_DLL + void setFilterOnWrite(bool); + QPDF_DLL + bool getFilterOnWrite(); + + // If addTokenFilter has been called for this stream, then the original data should be + // considered to be modified. This means we should avoid optimizations such as not filtering a + // stream that is already compressed. + QPDF_DLL + bool isDataModified(); + + // Returns filtered (uncompressed) stream data. Throws an exception if the stream is filtered + // and we can't decode it. + QPDF_DLL + std::shared_ptr getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized); + + // Returns unfiltered (raw) stream data. + QPDF_DLL + std::shared_ptr getRawStreamData(); + + // Write stream data through the given pipeline. A null pipeline value may be used if all you + // want to do is determine whether a stream is filterable and would be filtered based on the + // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags + // alter the behavior in the following way: + // + // encode_flags: + // + // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are + // applied. + // + // qpdf_sf_normalize -- tokenize as content stream and normalize tokens + // + // decode_level: + // + // qpdf_dl_none -- do not decode any streams. + // + // qpdf_dl_generalized -- decode supported general-purpose filters. This includes + // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode. + // + // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy + // specialized filters. This includes /RunLengthDecode. + // + // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported + // lossy filters. This includes /DCTDecode. + // + // If, based on the flags and the filters and decode parameters, we determine that we know how + // to apply all requested filters, do so and return true if we are successful. + // + // The exact meaning of the return value differs the different versions of this function, but + // for any version, the meaning has been the same. For the main version, added in qpdf 10, the + // return value indicates whether the overall operation succeeded. The filter parameter, if + // specified, will be set to whether or not filtering was attempted. If filtering was not + // requested, this value will be false even if the overall operation succeeded. + // + // If filtering is requested but this method returns false, it means there was some error in the + // filtering, in which case the resulting data is likely partially filtered and/or incomplete + // and may not be consistent with the configured filters. QPDFWriter handles this by attempting + // to get the stream data without filtering, but callers should consider a false return value + // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry + // in that case, pass true as the value of will_retry. This changes the warning issued by the + // library to indicate that the operation will be retried without filtering to avoid data loss. + + // Return value is overall success, even if filtering is not requested. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + bool* filtering_attempted, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy version. Return value is whether filtering was attempted. There is no way to determine + // success if filtering was not attempted. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows: + // filter = false -> encode_flags = 0 + // filter = true -> decode_level = qpdf_dl_generalized + // normalize = true -> encode_flags |= qpdf_sf_normalize + // compress = true -> encode_flags |= qpdf_sf_compress + // Return value is whether filtering was attempted. + QPDF_DLL + bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress); + + // Replace a stream's dictionary. The new dictionary must be consistent with the stream's data. + // This is most appropriately used when creating streams from scratch that will use a stream + // data provider and therefore start with an empty dictionary. It may be more convenient in + // this case than calling getDict and modifying it for each key. The pdf-create example does + // this. + QPDF_DLL + void replaceDict(QPDFObjectHandle const&); + + // Test whether a stream is the root XMP /Metadata object of its owning QPDF. + QPDF_DLL + bool isRootMetadata() const; + + // REPLACING STREAM DATA + + // Note about all replaceStreamData methods: whatever values are passed as filter and + // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object + // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf + // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing + // values untouched. + + // Replace this stream's stream data with the given data buffer. The stream's /Length key is + // replaced with the length of the data buffer. The stream is interpreted as if the data read + // from the file, after any decryption filters have been applied, is as presented. + QPDF_DLL + void replaceStreamData( + std::shared_ptr data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Replace the stream's stream data with the given string. This method will create a copy of the + // data rather than using the user-provided buffer as in the std::shared_ptr version of + // replaceStreamData. + QPDF_DLL + void replaceStreamData( + std::string const& data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // As above, replace this stream's stream data. Instead of directly providing a buffer with the + // stream data, call the given provider's provideStreamData method. See comments on the + // StreamDataProvider class (defined above) for details on the method. The data must be + // consistent with filter and decode_parms as provided. Although it is more complex to use this + // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid + // allocating memory for the stream data. Example programs are provided that use both forms of + // replaceStreamData. + + // Note about stream length: for any given stream, the provider must provide the same amount of + // data each time it is called. This is critical for making linearization work properly. + // Versions of qpdf before 3.0.0 required a length to be specified here. Starting with + // version 3.0.0, this is no longer necessary (or permitted). The first time the stream data + // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is + // enforced that the length be the same as the first time. + + // If you have gotten a compile error here while building code that worked with older versions + // of qpdf, just omit the length parameter. You can also simplify your code by not having to + // compute the length in advance. + QPDF_DLL + void replaceStreamData( + std::shared_ptr provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider. + + // The provider should write the stream data to the pipeline. For a one-liner to replace stream + // data with the contents of a file, pass QUtil::file_provider(filename) as provider. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + // The provider should write the stream data to the pipeline, returning true if it succeeded + // without errors. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Access object ID and generation. For direct objects, return object ID 0. + + // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to + // the pattern of depending on object ID or generation without the other. In general, when + // keeping track of object IDs, it's better to use QPDFObjGen instead. + + QPDF_DLL + QPDFObjGen getObjGen() const; + QPDF_DLL + int getObjectID() const; + QPDF_DLL + int getGeneration() const; + + QPDF_DLL + std::string unparse() const; + QPDF_DLL + std::string unparseResolved() const; + // For strings only, force binary representation. Otherwise, same as unparse. + QPDF_DLL + std::string unparseBinary() const; + + // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available + // JSON version. The JSON is generated as follows: + // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their + // native JSON types. + // * Names are encoded as strings representing the canonical representation (after parsing #xx) + // and preceded by a slash, just as unparse() returns. For example, the JSON for the + // PDF-syntax name /Text#2fPlain would be "/Text/Plain". + // * Indirect references are encoded as strings containing "obj gen R" + // * Strings + // * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters + // encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode + // mappings are not reversible. There is no way to tell the difference between a string that + // looks like a name or indirect object from an actual name or indirect object. + // * JSON v2: + // * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally + // mapped to Unicode (which is all strings without undefined characters) are represented + // as "u:" followed by the UTF-8 encoded string. Example: + // "u:potato". + // * All other strings are represented as "b:" followed by a hexadecimal encoding of the + // string. Example: "b:0102cacb" + // * Streams + // * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a + // dictionary other than context. + // * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the + // stream's dictionary. Since "dict" does not otherwise represent anything, this is + // unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data. + // * Object types that are only valid in content streams (inline image, operator) are serialized + // as "null". Attempting to serialize a "reserved" object is an error. + // If dereference_indirect is true and this is an indirect object, show the actual contents of + // the object. The effect of dereference_indirect applies only to this object. It is not + // recursive. + QPDF_DLL + JSON getJSON(int json_version, bool dereference_indirect = false) const; + + // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient + // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the + // documentation for getJSON and JSON::write for further detail. + QPDF_DLL + void writeJSON( + int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const; + + // This method can be called on a stream to get a more extended JSON representation of the + // stream that includes the stream's data. The JSON object returned is always a dictionary whose + // "dict" key is an encoding of the stream's dictionary. The representation of the data is + // determined by the json_data field. + // + // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file. + // + // If json_data is qpdf_sj_none, stream data is not represented. + // + // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on + // the value of decode_level, which has the same meaning as with pipeStreamData. + // + // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data" + // field of the dictionary that is returned. + // + // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be + // supplied. The value of data_filename is stored in the resulting json in the "datafile" key + // but is not otherwise use. The stream data itself (raw or filtered depending on decode level), + // is written to the pipeline via pipeStreamData(). + // + // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must + // remain valid until after the JSON object is written. + QPDF_DLL + JSON getStreamJSON( + int json_version, + qpdf_json_stream_data_e json_data, + qpdf_stream_decode_level_e decode_level, + Pipeline* p, + std::string const& data_filename); + + // Legacy helper methods for commonly performed operations on pages. Newer code should use + // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as + // the identically named methods in that class, but newer functionality will be added there. + QPDF_DLL + std::map getPageImages(); + QPDF_DLL + std::vector getPageContents(); + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + QPDF_DLL + void rotatePage(int angle, bool relative); + QPDF_DLL + void coalesceContentStreams(); + // End legacy page helpers + + // Issue a warning about this object if possible. If the object has a description, a warning + // will be issued using the owning QPDF as context. Otherwise, a message will be written to the + // default logger's error stream, which is standard error if not overridden. Objects read + // normally from the file have descriptions. See comments on setObjectDescription for additional + // details. + QPDF_DLL + void warnIfPossible(std::string const& warning) const; + + // Convenience routine: Throws if the assumption is violated. Your code will be better if you + // call one of the isType methods and handle the case of the type being wrong, but these can be + // convenient if you have already verified the type. + QPDF_DLL + void assertInitialized() const; + + QPDF_DLL + void assertNull() const; + QPDF_DLL + void assertBool() const; + QPDF_DLL + void assertInteger() const; + QPDF_DLL + void assertReal() const; + QPDF_DLL + void assertName() const; + QPDF_DLL + void assertString() const; + QPDF_DLL + void assertOperator() const; + QPDF_DLL + void assertInlineImage() const; + QPDF_DLL + void assertArray() const; + QPDF_DLL + void assertDictionary() const; + QPDF_DLL + void assertStream() const; + QPDF_DLL + void assertReserved() const; + + QPDF_DLL + void assertIndirect() const; + QPDF_DLL + void assertScalar() const; + QPDF_DLL + void assertNumber() const; + + // The isPageObject method checks the /Type key of the object. This is not completely reliable + // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is + // slightly more accepting but may still return false here when treating the object as a page + // would work. Use this sparingly. + QPDF_DLL + bool isPageObject() const; + QPDF_DLL + bool isPagesObject() const; + QPDF_DLL + void assertPageObject() const; + + QPDF_DLL + bool isFormXObject() const; + + // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as + // images. + QPDF_DLL + bool isImage(bool exclude_imagemask = true) const; + + // The following methods do not form part of the public API and are for internal use only. + + QPDFObjectHandle(std::shared_ptr const& obj) : + qpdf::BaseHandle(obj) + { + } + QPDFObjectHandle(std::shared_ptr&& obj) : + qpdf::BaseHandle(std::move(obj)) + { + } + std::shared_ptr + getObj() + { + return obj; + } + + void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const; + + inline qpdf::Array as_array(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Dictionary as_dictionary(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const; + + private: + void typeWarning(char const* expected_type, std::string const& warning) const; + void objectWarning(std::string const& warning) const; + void assertType(char const* type_name, bool istype) const; + void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); + void setParsedOffset(qpdf_offset_t offset); + void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); + static void parseContentStream_data( + std::string_view stream_data, + std::string const& description, + ParserCallbacks* callbacks, + QPDF* context); + std::vector + arrayOrStreamToStreamArray(std::string const& description, std::string& all_description); + void checkOwnership(QPDFObjectHandle const&) const; +}; + +#ifndef QPDF_NO_QPDF_STRING +// This is short for QPDFObjectHandle::parse, so you can do + +// auto oh = "<< /Key (value) >>"_qpdf; + +// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration +// from being here. + +/* clang-format off */ + // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest + // of the file as a string if clang-format removes the space after "operator", and as of + // clang-format 15, there's no way to prevent it from doing so. + QPDF_DLL + QPDFObjectHandle operator ""_qpdf(char const* v, size_t len); +/* clang-format on */ + +#endif // QPDF_NO_QPDF_STRING + +class QPDFObjectHandle::QPDFDictItems +{ + // This class allows C++-style iteration, including range-for iteration, around dictionaries. + // You can write + + // for (auto iter: QPDFDictItems(dictionary_obj)) + // { + // // iter.first is a string + // // iter.second is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFDictItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFDictItems; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFDictItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + std::set keys; + std::set::iterator iter; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +class QPDFObjectHandle::QPDFArrayItems +{ + // This class allows C++-style iteration, including range-for iteration, around arrays. You can + // write + + // for (auto iter: QPDFArrayItems(array_obj)) + // { + // // iter is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFArrayItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFArrayItems; + + public: + typedef QPDFObjectHandle T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFArrayItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + int item_number; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +namespace qpdf +{ + inline BaseHandle:: + operator bool() const + { + return static_cast(obj); + } + + inline BaseHandle:: + operator QPDFObjectHandle() const + { + return {obj}; + } + +} // namespace qpdf + +inline bool +QPDFObjectHandle::isInitialized() const +{ + return obj != nullptr; +} + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjectHelper.hh new file mode 100644 index 0000000..d19ba3b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFObjectHelper.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJECTHELPER_HH +#define QPDFOBJECTHELPER_HH + +#include + +#include + +// This is a base class for QPDF Object Helper classes. Object helpers are classes that provide a +// convenient, higher-level API for working with specific types of QPDF objects. Object helpers are +// always initialized with a QPDFObjectHandle, and the underlying object handle can always be +// retrieved. The intention is that you may freely intermix use of object helpers with the +// underlying QPDF objects unless there is a specific comment in a specific helper method that says +// otherwise. The pattern of using helper objects was introduced to allow creation of higher level +// helper functions without polluting the public interface of QPDFObjectHandle. +class QPDF_DLL_CLASS QPDFObjectHelper: public qpdf::BaseHandle +{ + public: + QPDFObjectHelper(QPDFObjectHandle oh) : + qpdf::BaseHandle(oh.getObj()) + { + } + QPDF_DLL + virtual ~QPDFObjectHelper(); + QPDFObjectHandle + getObjectHandle() + { + return {obj}; + } + QPDFObjectHandle const + getObjectHandle() const + { + return {obj}; + } + + protected: + QPDF_DLL_PRIVATE + QPDFObjectHandle + oh() + { + return {obj}; + } + QPDF_DLL_PRIVATE + QPDFObjectHandle const + oh() const + { + return {obj}; + } + QPDFObjectHandle oh_; +}; + +#endif // QPDFOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFOutlineDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFOutlineDocumentHelper.hh new file mode 100644 index 0000000..66b4481 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFOutlineDocumentHelper.hh @@ -0,0 +1,92 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEDOCUMENTHELPER_HH +#define QPDFOUTLINEDOCUMENTHELPER_HH + +#include +#include +#include +#include +#include + +#include +#include + +#include + +// This is a document helper for outlines, also known as bookmarks. Outlines are discussed in +// section 12.3.3 of the PDF spec (ISO-32000). With the help of QPDFOutlineObjectHelper, the +// outlines tree is traversed, and a bidirectional map is made between pages and outlines. See also +// QPDFOutlineObjectHelper. +class QPDFOutlineDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFOutlineDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Outlines structure. This is useful if you have modified the structure of the + // Outlines dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFOutlineDocumentHelper(QPDF&); + + ~QPDFOutlineDocumentHelper() override = default; + + QPDF_DLL + bool hasOutlines(); + + QPDF_DLL + std::vector getTopLevelOutlines(); + + // If the name is a name object, look it up in the /Dests key of the document catalog. If the + // name is a string, look it up in the name tree pointed to by the /Dests key of the names + // dictionary. + QPDF_DLL + QPDFObjectHandle resolveNamedDest(QPDFObjectHandle name); + + // Return a list outlines that are known to target the specified page. + QPDF_DLL + std::vector getOutlinesForPage(QPDFObjGen); + + class Accessor + { + friend class QPDFOutlineObjectHelper; + + static bool checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen og); + }; + + private: + void initializeByPage(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFOutlineObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFOutlineObjectHelper.hh new file mode 100644 index 0000000..108ec59 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFOutlineObjectHelper.hh @@ -0,0 +1,109 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEOBJECTHELPER_HH +#define QPDFOUTLINEOBJECTHELPER_HH + +#include +#include +#include + +class QPDFOutlineDocumentHelper; + +#include + +// This is an object helper for outline items. Outlines, also known as bookmarks, are described in +// section 12.3.3 of the PDF spec (ISO-32000). See comments below for details. +class QPDFOutlineObjectHelper: public QPDFObjectHelper +{ + public: + ~QPDFOutlineObjectHelper() override + { + // This must be cleared explicitly to avoid circular references that prevent cleanup of + // shared pointers. + m->parent = nullptr; + } + + // All constructors are private. You can only create one of these using + // QPDFOutlineDocumentHelper. + + // Return parent pointer. Returns a null pointer if this is a top-level outline. + QPDF_DLL + std::shared_ptr getParent(); + + // Return children as a list. + QPDF_DLL + std::vector getKids(); + + // Return the destination, regardless of whether it is named or explicit and whether it is + // directly provided or in a GoTo action. Returns a null object if the destination can't be + // determined. Named destinations can be resolved using the older root /Dest dictionary or the + // current names tree. + QPDF_DLL + QPDFObjectHandle getDest(); + + // Return the page that the outline points to. Returns a null object if the destination page + // can't be determined. + QPDF_DLL + QPDFObjectHandle getDestPage(); + + // Returns the value of /Count as present in the object, or 0 if not present. If count is + // positive, the outline is open. If negative, it is closed. Either way, the absolute value is + // the number of descendant items that would be visible if this were open. + QPDF_DLL + int getCount(); + + // Returns the title as a UTF-8 string. Returns an empty string if there is no title. + QPDF_DLL + std::string getTitle(); + + class Accessor + { + friend class QPDFOutlineDocumentHelper; + + static QPDFOutlineObjectHelper + create(QPDFObjectHandle oh, QPDFOutlineDocumentHelper& dh, int depth) + { + return {oh, dh, depth}; + } + }; + + private: + QPDFOutlineObjectHelper(QPDFObjectHandle, QPDFOutlineDocumentHelper&, int); + + class Members + { + friend class QPDFOutlineObjectHelper; + + public: + ~Members() = default; + + private: + Members(QPDFOutlineDocumentHelper& dh); + Members(Members const&) = delete; + + QPDFOutlineDocumentHelper& dh; + std::shared_ptr parent; + std::vector kids; + }; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageDocumentHelper.hh new file mode 100644 index 0000000..a2cd9f8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageDocumentHelper.hh @@ -0,0 +1,128 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEDOCUMENTHELPER_HH +#define QPDFPAGEDOCUMENTHELPER_HH + +#include +#include +#include + +#include + +#include + +#include + +class QPDFAcroFormDocumentHelper; + +class QPDFPageDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFPageDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Pages structure. This is useful if you have modified the Pages structure in + // a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageDocumentHelper(QPDF&); + + ~QPDFPageDocumentHelper() override = default; + + // Traverse page tree, and return all /Page objects wrapped in QPDFPageObjectHelper objects. + // Unlike with QPDF::getAllPages, the vector of pages returned by this call is not affected by + // additions or removals of pages. If you manipulate pages, you will have to call this again to + // get a new copy. Please see comments in QPDF.hh for getAllPages() for additional details. + QPDF_DLL + std::vector getAllPages(); + + // The PDF /Pages tree allows inherited values. Working with the pages of a pdf is much easier + // when the inheritance is resolved by explicitly setting the values in each /Page. + QPDF_DLL + void pushInheritedAttributesToPage(); + + // This calls QPDFPageObjectHelper::removeUnreferencedResources for every page in the document. + // See comments in QPDFPageObjectHelper.hh for details. + QPDF_DLL + void removeUnreferencedResources(); + + // Add a new page at the beginning or the end of the current pdf. The newpage parameter may be + // either a direct object, an indirect object from this QPDF, or an indirect object from another + // QPDF. If it is a direct object, it will be made indirect. If it is an indirect object from + // another QPDF, this method will call pushInheritedAttributesToPage on the other file and then + // copy the page to this QPDF using the same underlying code as copyForeignObject. At this + // stage, if the indirect object is already in the pages tree, a shallow copy is made to avoid + // adding the same page more than once. In version 10.3.1 and earlier, adding a page that + // already existed would throw an exception and could cause qpdf to crash on subsequent page + // insertions in some cases. Note that this means that, in some cases, the page actually added + // won't be exactly the same object as the one passed in. If you want to do subsequent + // modification on the page, you should retrieve it again. + // + // Note that you can call copyForeignObject directly to copy a page from a different file, but + // the resulting object will not be a page in the new file. You could do this, for example, to + // convert a page into a form XObject, though for that, you're better off using + // QPDFPageObjectHelper::getFormXObjectForPage. + // + // This method does not have any specific awareness of annotations or form fields, so if you + // just add a page without thinking about it, you might end up with two pages that share form + // fields or annotations. While the page may look fine, it will probably not function properly + // with regard to interactive features. To work around this, you should call + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations. A future version of qpdf will likely + // provide a higher-level interface for copying pages around that will handle document-level + // constructs in a less error-prone fashion. + + QPDF_DLL + void addPage(QPDFPageObjectHelper newpage, bool first); + + // Add new page before or after refpage. See comments for addPage for details about what newpage + // should be. + QPDF_DLL + void addPageAt(QPDFPageObjectHelper newpage, bool before, QPDFPageObjectHelper refpage); + + // Remove page from the pdf. + QPDF_DLL + void removePage(QPDFPageObjectHelper page); + + // For every annotation, integrate the annotation's appearance stream into the containing page's + // content streams, merge the annotation's resources with the page's resources, and remove the + // annotation from the page. Handles widget annotations associated with interactive form fields + // as a special case, including removing the /AcroForm key from the document catalog. The values + // passed to required_flags and forbidden_flags are passed along to + // QPDFAnnotationObjectHelper::getPageContentForAppearance. See comments there in + // QPDFAnnotationObjectHelper.hh for meanings of those flags. + QPDF_DLL + void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageLabelDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageLabelDocumentHelper.hh new file mode 100644 index 0000000..51e2265 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageLabelDocumentHelper.hh @@ -0,0 +1,99 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGELABELDOCUMENTHELPER_HH +#define QPDFPAGELABELDOCUMENTHELPER_HH + +#include + +#include +#include + +#include + +// Page labels are discussed in the PDF spec (ISO-32000) in section 12.4.2. +// +// Page labels are implemented as a number tree. Each key is a page index, numbered from 0. The +// values are dictionaries with the following keys, all optional: +// +// * /Type: if present, must be /PageLabel +// * /S: one of /D, /R, /r, /A, or /a for decimal, upper-case and lower-case Roman numeral, or +// upper-case and lower-case alphabetic +// * /P: if present, a fixed prefix string that is prepended to each page number +// * /St: the starting number, or 1 if not specified + +class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the PageLabels structure, which can be expensive. + QPDF_DLL + static QPDFPageLabelDocumentHelper& get(QPDF& qpdf); + + // Re-validate the PageLabels structure. This is useful if you have modified the structure of + // the PageLabels dictionary in a way that could have invalidated the structure. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageLabelDocumentHelper(QPDF&); + + ~QPDFPageLabelDocumentHelper() override = default; + + QPDF_DLL + bool hasPageLabels(); + + // Helper function to create a dictionary suitable for adding to the /PageLabels numbers tree. + QPDF_DLL + static QPDFObjectHandle + pageLabelDict(qpdf_page_label_e label_type, int start_num, std::string_view prefix); + + // Return a page label dictionary representing the page label for the given page. The page does + // not need to appear explicitly in the page label dictionary. This method will adjust /St as + // needed to produce a label that is suitable for the page. + QPDF_DLL + QPDFObjectHandle getLabelForPage(long long page_idx); + + // Append to the incoming vector a list of objects suitable for inclusion in a /PageLabels + // dictionary's /Nums field. start_idx and end_idx are the indexes to the starting and ending + // pages (inclusive) in the original file, and new_start_idx is the index to the first page in + // the new file. For example, if pages 10 through 12 of one file are being copied to a new file + // as pages 6 through 8, you would call getLabelsForPageRange(10, 12, 6), which would return as + // many entries as are required to add to the new file's PageLabels. This method fabricates a + // suitable entry even if the original document has no page labels. This behavior facilitates + // using this function to incrementally build up a page labels tree when merging files. + QPDF_DLL + void getLabelsForPageRange( + long long start_idx, + long long end_idx, + long long new_start_idx, + std::vector& new_labels); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGELABELDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageObjectHelper.hh new file mode 100644 index 0000000..ef8346e --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFPageObjectHelper.hh @@ -0,0 +1,423 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEOBJECTHELPER_HH +#define QPDFPAGEOBJECTHELPER_HH + +#include +#include +#include + +#include + +#include +#include + +class QPDFAcroFormDocumentHelper; + +// This is a helper class for page objects, but as of qpdf 10.1, many of the methods also work +// for form XObjects. When this is the case, it is noted in the comment. +class QPDFPageObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFPageObjectHelper(QPDFObjectHandle); + + ~QPDFPageObjectHelper() override = default; + + // PAGE ATTRIBUTES + + // The getAttribute method works with pages and form XObjects. It returns the value of the + // requested attribute from the page/form XObject's dictionary, taking inheritance from the + // pages tree into consideration. For pages, the attributes /MediaBox, /CropBox, /Resources, and + // /Rotate are inheritable, meaning that if they are not present directly on the page node, they + // may be inherited from ancestor nodes in the pages tree. + // + // There are two ways that an attribute can be "shared": + // + // * For inheritable attributes on pages, it may appear in a higher level node of the pages tree + // + // * For any attribute, the attribute may be an indirect object which may be referenced by more + // than one page/form XObject. + // + // If copy_if_shared is true, then this method will replace the attribute with a shallow copy if + // it is indirect or inherited and return the copy. You should do this if you are going to + // modify the returned object and want the modifications to apply to the current page/form + // XObject only. + QPDF_DLL + QPDFObjectHandle getAttribute(std::string const& name, bool copy_if_shared); + + // PAGE BOXES + // + // Pages have various types of boundary boxes. These are described in detail in the PDF + // specification (section 14.11.2 Page boundaries). They are, by key in the page dictionary: + // + // * /MediaBox -- boundaries of physical page + // * /CropBox -- clipping region of what is displayed + // * /BleedBox -- clipping region for production environments + // * /TrimBox -- dimensions of final printed page after trimming + // * /ArtBox -- extent of meaningful content including margins + // + // Of these, only /MediaBox is required. If any are absent, the + // fallback value for /CropBox is /MediaBox, and the fallback + // values for the other boxes are /CropBox. + // + // As noted above (PAGE ATTRIBUTES), /MediaBox and /CropBox can be inherited from parent nodes + // in the pages tree. The other boxes can't be inherited. + // + // When the comments below refer to the "effective value" of a box, this takes into + // consideration both inheritance through the pages tree (in the case of /MediaBox and /CropBox) + // and fallback values for missing attributes (for all except /MediaBox). + // + // For the methods below, copy_if_shared is passed to getAttribute and therefore refers only to + // indirect objects and values that are inherited through the pages tree. + // + // If copy_if_fallback is true, a copy is made if the object's value was obtained by falling + // back to a different box. + // + // The copy_if_shared and copy_if_fallback parameters carry across multiple layers. This is + // explained below. + // + // You should set copy_if_shared to true if you want to modify a bounding box for the current + // page without affecting other pages but you don't want to change the fallback behavior. For + // example, if you want to modify the /TrimBox for the current page only but have it continue to + // fall back to the value of /CropBox or /MediaBox if they are not defined, you could set + // copy_if_shared to true. + // + // You should set copy_if_fallback to true if you want to modify a specific box as distinct from + // any other box. For example, if you want to make /TrimBox differ from /CropBox, then you + // should set copy_if_fallback to true. + // + // The copy_if_fallback flags were added in qpdf 11. + // + // For example, suppose that neither /CropBox nor /TrimBox is present on a page but /CropBox is + // present in the page's parent node in the page tree. + // + // * getTrimBox(false, false) would return the /CropBox from the parent node. + // + // * getTrimBox(true, false) would make a shallow copy of the /CropBox from the parent node into + // the current node and return it. + // + // * getTrimBox(false, true) would make a shallow copy of the /CropBox from the parent node into + // /TrimBox of the current node and return it. + // + // * getTrimBox(true, true) would make a shallow copy of the /CropBox from the parent node into + // the current node, then make a shallow copy of the resulting copy to /TrimBox of the current + // node, and then return that. + // + // To illustrate how these parameters carry across multiple layers, suppose that neither + // /MediaBox, /CropBox, nor /TrimBox is present on a page but /MediaBox is present on the + // parent. In this case: + // + // * getTrimBox(false, false) would return the value of /MediaBox from the parent node. + // + // * getTrimBox(true, false) would copy /MediaBox to the current node and return it. + // + // * getTrimBox(false, true) would first copy /MediaBox from the parent to /CropBox, then copy + // /CropBox to /TrimBox, and then return the result. + // + // * getTrimBox(true, true) would first copy /MediaBox from the parent to the current page, then + // copy it to /CropBox, then copy /CropBox to /TrimBox, and then return the result. + // + // If you need different behavior, call getAttribute directly and take care of your own copying. + + // Return the effective MediaBox + QPDF_DLL + QPDFObjectHandle getMediaBox(bool copy_if_shared = false); + + // Return the effective CropBox. If not defined, fall back to MediaBox + QPDF_DLL + QPDFObjectHandle getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective BleedBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective TrimBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective ArtBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Iterate through XObjects, possibly recursing into form XObjects. This works with pages or + // form XObjects. Call action on each XObject for which selector, if specified, returns true. + // With no selector, calls action for every object. In addition to the object being passed to + // action, the containing XObject dictionary and key are passed in. Remember that the XObject + // dictionary may be shared, and the object may appear in multiple XObject dictionaries. + QPDF_DLL + void forEachXObject( + bool recursive, + std::function action, + std::function selector = nullptr); + // Only call action for images + QPDF_DLL + void forEachImage( + bool recursive, + std::function action); + // Only call action for form XObjects + QPDF_DLL + void forEachFormXObject( + bool recursive, + std::function action); + + // Returns an empty map if there are no images or no resources. Prior to qpdf 8.4.0, this + // function did not support inherited resources, but it does now. Return value is a map from + // XObject name to the image object, which is always a stream. Works with form XObjects as well + // as pages. This method does not recurse into nested form XObjects. For that, use forEachImage. + QPDF_DLL + std::map getImages(); + + // Old name -- calls getImages() + QPDF_DLL + std::map getPageImages(); + + // Returns an empty map if there are no form XObjects or no resources. Otherwise, returns a map + // of keys to form XObjects directly referenced from this page or form XObjects. This does not + // recurse into nested form XObjects. For that, use forEachFormXObject. + QPDF_DLL + std::map getFormXObjects(); + + // Converts each inline image to an external (normal) image if the size is at least the + // specified number of bytes. This method works with pages or form XObjects. By default, it + // recursively processes nested form XObjects. Pass true as shallow to avoid this behavior. + // Prior to qpdf 10.1, form XObjects were ignored, but this was considered a bug. + QPDF_DLL + void externalizeInlineImages(size_t min_size = 0, bool shallow = false); + + // Return the annotations in the page's "/Annots" list, if any. If only_subtype is non-empty, + // only include annotations of the given subtype. + QPDF_DLL + std::vector getAnnotations(std::string const& only_subtype = ""); + + // Returns a vector of stream objects representing the content streams for the given page. This + // routine allows the caller to not care whether there are one or more than one content streams + // for a page. + QPDF_DLL + std::vector getPageContents(); + + // Add the given object as a new content stream for this page. If parameter 'first' is true, add + // to the beginning. Otherwise, add to the end. This routine automatically converts the page + // contents to an array if it is a scalar, allowing the caller not to care what the initial + // structure is. You can call coalesceContentStreams() afterwards if you want to force it to be + // a single stream. + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + + // Rotate a page. If relative is false, set the rotation of the page to angle. Otherwise, add + // angle to the rotation of the page. Angle must be a multiple of 90. Adding 90 to the rotation + // rotates clockwise by 90 degrees. + QPDF_DLL + void rotatePage(int angle, bool relative); + + // Coalesce a page's content streams. A page's content may be a stream or an array of streams. + // If this page's content is an array, concatenate the streams into a single stream. This can be + // useful when working with files that split content streams in arbitrary spots, such as in the + // middle of a token, as that can confuse some software. You could also call this after calling + // addPageContents. + QPDF_DLL + void coalesceContentStreams(); + + // + // Content stream handling + // + + // Parse a page's contents through ParserCallbacks, described above. This method works whether + // the contents are a single stream or an array of streams. Call on a page object. Also works + // for form XObjects. + QPDF_DLL + void parseContents(QPDFObjectHandle::ParserCallbacks* callbacks); + // Old name + QPDF_DLL + void parsePageContents(QPDFObjectHandle::ParserCallbacks* callbacks); + + // Pass a page's or form XObject's contents through the given TokenFilter. If a pipeline is also + // provided, it will be the target of the write methods from the token filter. If a pipeline is + // not specified, any output generated by the token filter will be discarded. Use this interface + // if you need to pass a page's contents through filter for work purposes without having that + // filter automatically applied to the page's contents, as happens with addContentTokenFilter. + // See examples/pdf-count-strings.cc for an example. + QPDF_DLL + void filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Old name -- calls filterContents() + QPDF_DLL + void filterPageContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Pipe a page's contents through the given pipeline. This method works whether the contents are + // a single stream or an array of streams. Also works on form XObjects. + QPDF_DLL + void pipeContents(Pipeline* p); + // Old name + QPDF_DLL + void pipePageContents(Pipeline* p); + + // Attach a token filter to a page's contents. If the page's contents is an array of streams, it + // is automatically coalesced. The token filter is applied to the page's contents as a single + // stream. Also works on form XObjects. + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + + // A page's resources dictionary maps names to objects elsewhere in the file. This method walks + // through a page's contents and keeps tracks of which resources are referenced somewhere in the + // contents. Then it removes from the resources dictionary any object that is not referenced in + // the contents. This operation is most useful after calling + // QPDFPageDocumentHelper::pushInheritedAttributesToPage(). This method is used by page + // splitting code to avoid copying unused objects in files that used shared resource + // dictionaries across multiple pages. This method recurses into form XObjects and can be called + // with a form XObject as well as a page. + QPDF_DLL + void removeUnreferencedResources(); + + // Return a new QPDFPageObjectHelper that is a duplicate of the page. The returned object is an + // indirect object that is ready to be inserted into the same or a different QPDF object using + // any of the addPage methods in QPDFPageDocumentHelper or QPDF. Without calling one of those + // methods, the page will not be added anywhere. The new page object shares all content streams + // and indirect object resources with the original page, so if you are going to modify the + // contents or other aspects of the page, you will need to handling copying of the component + // parts separately. + QPDF_DLL + QPDFPageObjectHelper shallowCopyPage(); + + // Return a transformation matrix whose effect is the same as the page's /Rotate and /UserUnit + // parameters. If invert is true, return a matrix whose effect is the opposite. The regular + // matrix is suitable for taking something from this page to put elsewhere, and the second one + // is suitable for putting something else onto this page. The page's TrimBox is used as the + // bounding box for purposes of computing the matrix. + QPDF_DLL + QPDFObjectHandle::Matrix getMatrixForTransformations(bool invert = false); + + // Return a form XObject that draws this page. This is useful for n-up operations, underlay, + // overlay, thumbnail generation, or any other case in which it is useful to replicate the + // contents of a page in some other context. The dictionaries are shallow copies of the original + // page dictionary, and the contents are coalesced from the page's contents. The resulting + // object handle is not referenced anywhere. If handle_transformations is true, the resulting + // form XObject's /Matrix will be set to replicate rotation (/Rotate) and scaling (/UserUnit) in + // the page's dictionary. In this way, the page's transformations will be preserved when placing + // this object on another page. + QPDF_DLL + QPDFObjectHandle getFormXObjectForPage(bool handle_transformations = true); + + // Return content stream text that will place the given form XObject (fo) using the resource + // name "name" on this page centered within the given rectangle. If invert_transformations is + // true, the effect of any rotation (/Rotate) and scaling (/UserUnit) applied to the current + // page will be inverted in the form XObject placement. This will cause the form XObject's + // absolute orientation to be preserved. You could overlay one page on another by calling + // getFormXObjectForPage on the original page, QPDFObjectHandle::getUniqueResourceName on the + // destination page's Resources dictionary to generate a name for the resulting object, and + // calling placeFormXObject on the destination page. Then insert the new fo (or, if it comes + // from a different file, the result of calling copyForeignObject on it) into the resources + // dictionary using name, and append or prepend the content to the page's content streams. See + // the overlay/underlay code in qpdf.cc or examples/pdf-overlay-page.cc for an example. From + // qpdf 10.0.0, the allow_shrink and allow_expand parameters control whether the form XObject is + // allowed to be shrunk or expanded to stay within or maximally fill the destination rectangle. + // The default values are for backward compatibility with the pre-10.0.0 behavior. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Alternative version that also fills in the transformation matrix that was used. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + QPDFMatrix& cm, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Return the transformation matrix that translates from the given form XObject's coordinate + // system into the given rectangular region on the page. The parameters have the same meaning as + // for placeFormXObject. + QPDF_DLL + QPDFMatrix getMatrixForFormXObjectPlacement( + QPDFObjectHandle fo, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // If a page is rotated using /Rotate in the page's dictionary, instead rotate the page by the + // same amount by altering the contents and removing the /Rotate key. This method adjusts the + // various page bounding boxes (/MediaBox, etc.) so that the page will have the same semantics. + // This can be useful to work around problems with PDF applications that can't properly handle + // rotated pages. If a QPDFAcroFormDocumentHelper is provided, it will be used for resolving any + // form fields that have to be rotated. If not, one will be created inside the function, which + // is less efficient. + QPDF_DLL + void flattenRotation(QPDFAcroFormDocumentHelper* afdh = nullptr); + + // Copy annotations from another page into this page. The other page may be from the same QPDF + // or from a different QPDF. Each annotation's rectangle is transformed by the given matrix. If + // the annotation is a widget annotation that is associated with a form field, the form field is + // copied into this document's AcroForm dictionary as well. You can use this to copy annotations + // from a page that was converted to a form XObject and added to another page. For example of + // this, see examples/pdf-overlay-page.cc. This method calls + // QPDFAcroFormDocumentHelper::transformAnnotations, which will copy annotations and form fields + // so that you can copy annotations from a source page to any number of other pages, even with + // different matrices, and maintain independence from the original annotations. See also + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations, which can be used if you copy a page and + // want to repair the annotations on the destination page to make them independent from the + // original page's annotations. + // + // If you pass in a QPDFAcroFormDocumentHelper*, the method will use that instead of creating + // one in the function. Creating QPDFAcroFormDocumentHelper objects is expensive, so if you're + // doing a lot of copying, it can be more efficient to create these outside and pass them in. + QPDF_DLL + void copyAnnotations( + QPDFPageObjectHelper from_page, + QPDFMatrix const& cm = QPDFMatrix(), + QPDFAcroFormDocumentHelper* afdh = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + private: + QPDFObjectHandle getAttribute( + std::string const& name, + bool copy_if_shared, + std::function get_fallback, + bool copy_if_fallback); + static bool + removeUnreferencedResourcesHelper(QPDFPageObjectHelper ph, std::set& unresolved); + + class Members + { + friend class QPDFPageObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFStreamFilter.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFStreamFilter.hh new file mode 100644 index 0000000..5cba242 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFStreamFilter.hh @@ -0,0 +1,67 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSTREAMFILTER_HH +#define QPDFSTREAMFILTER_HH + +#include +#include +#include + +class QPDF_DLL_CLASS QPDFStreamFilter +{ + public: + QPDFStreamFilter() = default; + + virtual ~QPDFStreamFilter() = default; + + // A QPDFStreamFilter class must implement, at a minimum, setDecodeParms() and + // getDecodePipeline(). QPDF will always call setDecodeParms() before calling + // getDecodePipeline(). It is expected that you will store any needed information from + // decode_parms (or the decode_parms object itself) in your instance so that it can be used to + // construct the decode pipeline. + + // Return a boolean indicating whether your filter can proceed with the given /DecodeParms. The + // default implementation accepts a null object and rejects everything else. + QPDF_DLL + virtual bool setDecodeParms(QPDFObjectHandle decode_parms); + + // Return a pipeline that will decode data encoded with your filter. Your implementation must + // ensure that the pipeline is deleted when the instance of your class is destroyed. + QPDF_DLL + virtual Pipeline* getDecodePipeline(Pipeline* next) = 0; + + // If your filter implements "specialized" compression or lossy compression, override one or + // both of these methods. The default implementations return false. See comments in QPDFWriter + // for details. QPDF defines specialized compression as non-lossy compression not intended for + // general-purpose data. qpdf, by default, doesn't mess with streams that are compressed with + // specialized compression, the idea being that the decision to use that compression scheme + // would fall outside of what QPDFWriter would know anything about, so any attempt to decode and + // re-encode would probably be undesirable. + QPDF_DLL + virtual bool isSpecializedCompression(); + QPDF_DLL + virtual bool isLossyCompression(); + + private: + QPDFStreamFilter(QPDFStreamFilter const&) = delete; + QPDFStreamFilter& operator=(QPDFStreamFilter const&) = delete; +}; + +#endif // QPDFSTREAMFILTER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFSystemError.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFSystemError.hh new file mode 100644 index 0000000..94e0ab0 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFSystemError.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSYSTEMERROR_HH +#define QPDFSYSTEMERROR_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error +{ + public: + QPDF_DLL + QPDFSystemError(std::string const& description, int system_errno); + + ~QPDFSystemError() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. + + QPDF_DLL + std::string const& getDescription() const; + QPDF_DLL + int getErrno() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat(std::string const& description, int system_errno); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + std::string description; + int system_errno; +}; + +#endif // QPDFSYSTEMERROR_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFTokenizer.hh new file mode 100644 index 0000000..94dae1a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFTokenizer.hh @@ -0,0 +1,218 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFTOKENIZER_HH +#define QPDFTOKENIZER_HH + +#include + +#include + +#include +#include +#include + +namespace qpdf +{ + class Tokenizer; + namespace impl + { + class Parser; + } +} // namespace qpdf + +class QPDFTokenizer +{ + public: + // Token type tt_eof is only returned of allowEOF() is called on the tokenizer. tt_eof was + // introduced in QPDF version 4.1. tt_space, tt_comment, and tt_inline_image were added in QPDF + // version 8. + enum token_type_e { + tt_bad, + tt_array_close, + tt_array_open, + tt_brace_close, + tt_brace_open, + tt_dict_close, + tt_dict_open, + tt_integer, + tt_name, + tt_real, + tt_string, + tt_null, + tt_bool, + tt_word, + tt_eof, + tt_space, + tt_comment, + tt_inline_image, + }; + + class Token + { + public: + Token() : + type(tt_bad) + { + } + QPDF_DLL + Token(token_type_e type, std::string const& value); + Token( + token_type_e type, + std::string const& value, + std::string raw_value, + std::string error_message) : + type(type), + value(value), + raw_value(raw_value), + error_message(error_message) + { + } + token_type_e + getType() const + { + return this->type; + } + std::string const& + getValue() const + { + return this->value; + } + std::string const& + getRawValue() const + { + return this->raw_value; + } + std::string const& + getErrorMessage() const + { + return this->error_message; + } + bool + operator==(Token const& rhs) const + { + // Ignore fields other than type and value + return ( + (this->type != tt_bad) && (this->type == rhs.type) && (this->value == rhs.value)); + } + bool + isInteger() const + { + return this->type == tt_integer; + } + bool + isWord() const + { + return this->type == tt_word; + } + bool + isWord(std::string const& value) const + { + return this->type == tt_word && this->value == value; + } + + private: + token_type_e type; + std::string value; + std::string raw_value; + std::string error_message; + }; + + QPDF_DLL + QPDFTokenizer(); + + QPDF_DLL + ~QPDFTokenizer(); + + // If called, treat EOF as a separate token type instead of an error. This was introduced in + // QPDF 4.1 to facilitate tokenizing content streams. + QPDF_DLL + void allowEOF(); + + // If called, readToken will return "ignorable" tokens for space and comments. This was added in + // QPDF 8. + QPDF_DLL + void includeIgnorable(); + + // There are two modes of operation: push and pull. The pull method is easier but requires an + // input source. The push method is more complicated but can be used to tokenize a stream of + // incoming characters in a pipeline. + + // Push mode: + + // deprecated, please see + + // Keep presenting characters with presentCharacter() and presentEOF() and calling getToken() + // until getToken() returns true. When it does, be sure to check unread_ch and to unread ch if + // it is true. If these are called when a token is available, an exception will be thrown. + QPDF_DLL + void presentCharacter(char ch); + QPDF_DLL + void presentEOF(); + + // If a token is available, return true and initialize token with the token, unread_char with + // whether or not we have to unread the last character, and if unread_char, ch with the + // character to unread. + QPDF_DLL + bool getToken(Token& token, bool& unread_char, char& ch); + + // This function returns true of the current character is between tokens (i.e., white space that + // is not part of a string) or is part of a comment. A tokenizing filter can call this to + // determine whether to output the character. + [[deprecated("see ")]] QPDF_DLL bool + betweenTokens(); + + // Pull mode: + + // Read a token from an input source. Context describes the context in which the token is being + // read and is used in the exception thrown if there is an error. After a token is read, the + // position of the input source returned by input->tell() points to just after the token, and + // the input source's "last offset" as returned by input->getLastOffset() points to the + // beginning of the token. + QPDF_DLL + Token readToken( + InputSource& input, std::string const& context, bool allow_bad = false, size_t max_len = 0); + QPDF_DLL + Token readToken( + std::shared_ptr input, + std::string const& context, + bool allow_bad = false, + size_t max_len = 0); + + // Calling this method puts the tokenizer in a state for reading inline images. You should call + // this method after reading the character following the ID operator. In that state, it will + // return all data up to BUT NOT INCLUDING the next EI token. After you call this method, the + // next call to readToken (or the token created next time getToken returns true) will either be + // tt_inline_image or tt_bad. This is the only way readToken + // returns a tt_inline_image token. + QPDF_DLL + void expectInlineImage(std::shared_ptr input); + QPDF_DLL + void expectInlineImage(InputSource& input); + + private: + friend class qpdf::impl::Parser; + + QPDFTokenizer(QPDFTokenizer const&) = delete; + QPDFTokenizer& operator=(QPDFTokenizer const&) = delete; + + std::unique_ptr m; +}; + +#endif // QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFUsage.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFUsage.hh new file mode 100644 index 0000000..3c5da1b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFUsage.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFUSAGE_HH +#define QPDFUSAGE_HH + +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error +{ + public: + QPDF_DLL + QPDFUsage(std::string const& msg); + ~QPDFUsage() noexcept override = default; +}; + +#endif // QPDFUSAGE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFWriter.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFWriter.hh new file mode 100644 index 0000000..3c3c0b9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFWriter.hh @@ -0,0 +1,455 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFWRITER_HH +#define QPDFWRITER_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace qpdf +{ + class Writer; +} + +class QPDF; + +// This class implements a simple writer for saving QPDF objects to new PDF files. See comments +// through the header file for additional details. +class QPDFWriter +{ + public: + // Construct a QPDFWriter object without specifying output. You must call one of the output + // setting routines defined below. + QPDF_DLL + QPDFWriter(QPDF& pdf); + + // Create a QPDFWriter object that writes its output to a file or to stdout. This is equivalent + // to using the previous constructor and then calling setOutputFilename(). See + // setOutputFilename() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* filename); + + // Create a QPDFWriter object that writes its output to an already open FILE*. This is + // equivalent to calling the first constructor and then calling setOutputFile(). See + // setOutputFile() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* description, FILE* file, bool close_file); + + ~QPDFWriter() = default; + + class QPDF_DLL_CLASS ProgressReporter + { + public: + QPDF_DLL + virtual ~ProgressReporter(); + + // This method is called with a value from 0 to 100 to indicate approximate progress through + // the write process. See registerProgressReporter. + virtual void reportProgress(int) = 0; + }; + + // This is a progress reporter that takes a function. It is used by the C APIs, but it is + // available if you want to just register a C function as a handler. + class QPDF_DLL_CLASS FunctionProgressReporter: public ProgressReporter + { + public: + QPDF_DLL + FunctionProgressReporter(std::function); + QPDF_DLL + ~FunctionProgressReporter() override; + QPDF_DLL + void reportProgress(int) override; + + private: + std::function handler; + }; + + // Setting Output. Output may be set only one time. If you don't use the filename version of + // the QPDFWriter constructor, you must call exactly one of these methods. + + // Passing nullptr as filename means write to stdout. QPDFWriter will create a zero-length + // output file upon construction. If write fails, the empty or partially written file will not + // be deleted. This is by design: sometimes the partial file may be useful for tracking down + // problems. If your application doesn't want the partially written file to be left behind, you + // should delete it if the eventual call to write fails. + QPDF_DLL + void setOutputFilename(char const* filename); + + // Write to the given FILE*, which must be opened by the caller. If close_file is true, + // QPDFWriter will close the file. Otherwise, the caller must close the file. The file does not + // need to be seekable; it will be written to in a single pass. It must be open in binary mode. + QPDF_DLL + void setOutputFile(char const* description, FILE* file, bool close_file); + + // Indicate that QPDFWriter should create a memory buffer to contain the final PDF file. Obtain + // the memory by calling getBuffer(). + QPDF_DLL + void setOutputMemory(); + + // Return the buffer object containing the PDF file. If setOutputMemory() has been called, this + // method may be called exactly one time after write() has returned. The caller is responsible + // for deleting the buffer when done. See also getBufferSharedPointer(). + QPDF_DLL + Buffer* getBuffer(); + + // Return getBuffer() in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // Supply your own pipeline object. Output will be written to this pipeline, and QPDFWriter + // will call finish() on the pipeline. It is the caller's responsibility to manage the memory + // for the pipeline. The pipeline is never deleted by QPDFWriter, which makes it possible for + // you to call additional methods on the pipeline after the writing is finished. + QPDF_DLL + void setOutputPipeline(Pipeline*); + + // Setting Parameters + + // Set the value of object stream mode. In disable mode, we never generate any object streams. + // In preserve mode, we preserve object stream structure from the original file. In generate + // mode, we generate our own object streams. In all cases, we generate a conventional + // cross-reference table if there are no object streams and a cross-reference stream if there + // are object streams. The default is o_preserve. + QPDF_DLL + void setObjectStreamMode(qpdf_object_stream_e); + + // Set value of stream data mode. This is an older interface. Instead of using this, prefer + // setCompressStreams() and setDecodeLevel(). This method is retained for compatibility, but it + // does not cover the full range of available configurations. The mapping between this and the + // new methods is as follows: + // + // qpdf_s_uncompress: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_generalized) + // qpdf_s_preserve: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_none) + // qpdf_s_compress: + // setCompressStreams(true) + // setDecodeLevel(qpdf_dl_generalized) + // + // The default is qpdf_s_compress. + QPDF_DLL + void setStreamDataMode(qpdf_stream_data_e); + + // If true, compress any uncompressed streams when writing them. Metadata streams are a special + // case and are not compressed even if this is true. This is true by default for QPDFWriter. If + // you want QPDFWriter to leave uncompressed streams uncompressed, pass false to this method. + QPDF_DLL + void setCompressStreams(bool); + + // When QPDFWriter encounters streams, this parameter controls the behavior with respect to + // attempting to apply any filters to the streams when copying to the output. The decode levels + // are as follows: + // + // qpdf_dl_none: Do not attempt to apply any filters. Streams remain as they appear in the + // original file. Note that uncompressed streams may still be compressed on output. You can + // disable that by calling setCompressStreams(false). + // + // qpdf_dl_generalized: This is the default. QPDFWriter will apply LZWDecode, ASCII85Decode, + // ASCIIHexDecode, and FlateDecode filters on the input. When combined with + // setCompressStreams(true), which is the default, the effect of this is that streams filtered + // with these older and less efficient filters will be recompressed with the Flate filter. By + // default, as a special case, if a stream is already compressed with FlateDecode and + // setCompressStreams is enabled, the original compressed data will be preserved. This behavior + // can be overridden by calling setRecompressFlate(true). + // + // qpdf_dl_specialized: In addition to uncompressing the generalized compression formats, + // supported non-lossy compression will also be decoded. At present, this includes the + // RunLengthDecode filter. + // + // qpdf_dl_all: In addition to generalized and non-lossy specialized filters, supported lossy + // compression filters will be applied. At present, this includes DCTDecode (JPEG) compression. + // Note that compressing the resulting data with DCTDecode again will accumulate loss, so avoid + // multiple compression and decompression cycles. This is mostly useful for retrieving image + // data. + QPDF_DLL + void setDecodeLevel(qpdf_stream_decode_level_e); + + // By default, when both the input and output contents of a stream are compressed with Flate, + // qpdf does not uncompress and recompress the stream. Passing true here causes it to do so. + // This can be useful if recompressing all streams with a higher compression level, which can be + // set by calling the static method Pl_Flate::setCompressionLevel. + QPDF_DLL + void setRecompressFlate(bool); + + // Set value of content stream normalization. The default is "false". If true, we attempt to + // normalize newlines inside of content streams. Some constructs such as inline images may + // thwart our efforts. There may be some cases where this can damage the content stream. This + // flag should be used only for debugging and experimenting with PDF content streams. Never use + // it for production files. + QPDF_DLL + void setContentNormalization(bool); + + // Set QDF mode. QDF mode causes special "pretty printing" of PDF objects, adds comments for + // easier perusing of files. Resulting PDF files can be edited in a text editor and then run + // through fix-qdf to update cross reference tables and stream lengths. + QPDF_DLL + void setQDFMode(bool); + + // Preserve unreferenced objects. The default behavior is to discard any object that is not + // visited during a traversal of the object structure from the trailer. + QPDF_DLL + void setPreserveUnreferencedObjects(bool); + + // Always write a newline before the endstream keyword. This helps with PDF/A compliance, though + // it is not sufficient for it. + QPDF_DLL + void setNewlineBeforeEndstream(bool); + + // Set the minimum PDF version. If the PDF version of the input file (or previously set minimum + // version) is less than the version passed to this method, the PDF version of the output file + // will be set to this value. If the original PDF file's version or previously set minimum + // version is already this version or later, the original file's version will be used. + // QPDFWriter automatically sets the minimum version to 1.4 when R3 encryption parameters are + // used, and to 1.5 when object streams are used. + QPDF_DLL + void setMinimumPDFVersion(std::string const&, int extension_level = 0); + QPDF_DLL + void setMinimumPDFVersion(PDFVersion const&); + + // Force the PDF version of the output file to be a given version. Use of this function may + // create PDF files that will not work properly with older PDF viewers. When a PDF version is + // set using this function, qpdf will use this version even if the file contains features that + // are not supported in that version of PDF. In other words, you should only use this function + // if you are sure the PDF file in question has no features of newer versions of PDF or if you + // are willing to create files that old viewers may try to open but not be able to properly + // interpret. If any encryption has been applied to the document either explicitly or by + // preserving the encryption of the source document, forcing the PDF version to a value too low + // to support that type of encryption will explicitly disable decryption. Additionally, forcing + // to a version below 1.5 will disable object streams. + QPDF_DLL + void forcePDFVersion(std::string const&, int extension_level = 0); + + // Provide additional text to insert in the PDF file somewhere near the beginning of the file. + // This can be used to add comments to the beginning of a PDF file, for example, if those + // comments are to be consumed by some other application. No checks are performed to ensure + // that the text inserted here is valid PDF. If you want to insert multiline comments, you will + // need to include \n in the string yourself and start each line with %. An extra newline will + // be appended if one is not already present at the end of your text. + QPDF_DLL + void setExtraHeaderText(std::string const&); + + // Causes a deterministic /ID value to be generated. When this is set, the current time and + // output file name are not used as part of /ID generation. Instead, a digest of all significant + // parts of the output file's contents is included in the /ID calculation. Use of a + // deterministic /ID can be handy when it is desirable for a repeat of the same qpdf operation + // on the same inputs being written to the same outputs with the same parameters to generate + // exactly the same results. This feature is incompatible with encrypted files because, for + // encrypted files, the /ID is generated before any part of the file is written since it is an + // input to the encryption process. + QPDF_DLL + void setDeterministicID(bool); + + // Cause a static /ID value to be generated. Use only in test suites. See also + // setDeterministicID. + QPDF_DLL + void setStaticID(bool); + + // Use a fixed initialization vector for AES-CBC encryption. This is not secure. It should be + // used only in test suites for creating predictable encrypted output. + QPDF_DLL + void setStaticAesIV(bool); + + // Suppress inclusion of comments indicating original object IDs when writing QDF files. This + // can also be useful for testing, particularly when using comparison of two qdf files to + // determine whether two PDF files have identical content. + QPDF_DLL + void setSuppressOriginalObjectIDs(bool); + + // Preserve encryption. The default is true unless prefiltering, content normalization, or qdf + // mode has been selected in which case encryption is never preserved. Encryption is also not + // preserved if we explicitly set encryption parameters. + QPDF_DLL + void setPreserveEncryption(bool); + + // Copy encryption parameters from another QPDF object. If you want to copy encryption from the + // object you are writing, call setPreserveEncryption(true) instead. + QPDF_DLL + void copyEncryptionParameters(QPDF&); + + // Set up for encrypted output. User and owner password both must be specified. Either or both + // may be the empty string. Note that qpdf does not apply any special treatment to the empty + // string, which makes it possible to create encrypted files with empty owner passwords and + // non-empty user passwords or with the same password for both user and owner. Some PDF reading + // products don't handle such files very well. Enabling encryption disables stream prefiltering + // and content normalization. Note that setting R2 encryption parameters sets the PDF version + // to at least 1.3, setting R3 encryption parameters pushes the PDF version number to at + // least 1.4, setting R4 parameters pushes the version to at least 1.5, or if AES is used, 1.6, + // and setting R5 or R6 parameters pushes the version to at least 1.7 with extension level 3. + // + // Note about Unicode passwords: the PDF specification requires passwords to be encoded with PDF + // Doc encoding for R <= 4 and UTF-8 for R >= 5. In all cases, these methods take strings of + // bytes as passwords. It is up to the caller to ensure that passwords are properly encoded. The + // qpdf command-line tool tries to do this, as discussed in the manual. If you are doing this + // from your own application, QUtil contains many transcoding functions that could be useful to + // you, most notably utf8_to_pdf_doc. + + // R2 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR2EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_print, + bool allow_modify, + bool allow_extract, + bool allow_annotate); + // R3 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR3EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print); + // When use_aes=false, this call enables R4 with RC4, which is a weak cryptographic algorithm. + // Even with use_aes=true, the overall encryption scheme is weak. Don't use it unless you have + // to. See "Weak Cryptography" in the manual. This encryption format is deprecated in the + // PDF 2.0 specification. + QPDF_DLL + void setR4EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata, + bool use_aes); + // R5 is deprecated. Do not use it for production use. Writing R5 is supported by qpdf + // primarily to generate test files for applications that may need to test R5 support. + QPDF_DLL + void setR5EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata); + // This is the only password-based encryption format supported by the PDF specification. + QPDF_DLL + void setR6EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata_aes); + + // Create linearized output. Disables qdf mode, content normalization, and stream prefiltering. + QPDF_DLL + void setLinearization(bool); + + // For debugging QPDF: provide the name of a file to write pass1 of linearization to. The only + // reason to use this is to debug QPDF. To linearize, QPDF writes out the file in two passes. + // Usually the first pass is discarded, but lots of computations are made in pass 1. If a + // linearized file comes out wrong, it can be helpful to look at the first pass. + QPDF_DLL + void setLinearizationPass1Filename(std::string const&); + + // Create PCLm output. This is only useful for clients that know how to create PCLm files. If a + // file is structured exactly as PCLm requires, this call will tell QPDFWriter to write the PCLm + // header, create certain unreferenced streams required by the standard, and write the objects + // in the required order. Calling this on an ordinary PDF serves no purpose. There is no + // command-line argument that causes this method to be called. + QPDF_DLL + void setPCLm(bool); + + // If you want to be notified of progress, derive a class from ProgressReporter and override the + // reportProgress method. + QPDF_DLL + void registerProgressReporter(std::shared_ptr); + + // Return the PDF version that will be written into the header. Calling this method does all the + // preparation for writing, so it is an error to call any methods that may cause a change to the + // version. Adding new objects to the original file after calling this may also cause problems. + // It is safe to update existing objects or stream contents after calling this method, e.g., to + // include the final version number in metadata. + QPDF_DLL + std::string getFinalVersion(); + + // Write the final file. There is no expectation of being able to call write() more than once. + QPDF_DLL + void write(); + + // Return renumbered ObjGen that was written into the final file. This method can be used after + // calling write(). + QPDF_DLL + QPDFObjGen getRenumberedObjGen(QPDFObjGen); + + // Return XRef entry that was written into the final file. This method can be used after calling + // write(). + QPDF_DLL + std::map getWrittenXRefTable(); + + // The following structs / classes are not part of the public API. + struct Object; + struct NewObject; + class ObjTable; + class NewObjTable; + + private: + friend class qpdf::Writer; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFWRITER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFXRefEntry.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFXRefEntry.hh new file mode 100644 index 0000000..3739131 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QPDFXRefEntry.hh @@ -0,0 +1,73 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFXREFENTRY_HH +#define QPDFXREFENTRY_HH + +#include +#include + +class QPDFXRefEntry +{ + public: + // Type constants are from the PDF spec section "Cross-Reference Streams": + // 0 = free entry; not used + // 1 = "uncompressed"; field 1 = offset + // 2 = "compressed"; field 1 = object stream number, field 2 = index + + // Create a type 0 "free" entry. + QPDF_DLL + QPDFXRefEntry(); + QPDF_DLL + QPDFXRefEntry(int type, qpdf_offset_t field1, int field2); + // Create a type 1 "uncompressed" entry. + QPDFXRefEntry(qpdf_offset_t offset) : + type(1), + field1(offset) + { + } + // Create a type 2 "compressed" entry. + QPDFXRefEntry(int stream_number, int index) : + type(2), + field1(stream_number), + field2(index) + { + } + + QPDF_DLL + int getType() const; + QPDF_DLL + qpdf_offset_t getOffset() const; // only for type 1 + QPDF_DLL + int getObjStreamNumber() const; // only for type 2 + QPDF_DLL + int getObjStreamIndex() const; // only for type 2 + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created. + + // The layout can be changed to reduce the size from 24 to 16 bytes. However, this would have a + // definite runtime cost. + int type{0}; + qpdf_offset_t field1{0}; + int field2{0}; +}; + +#endif // QPDFXREFENTRY_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QTC.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QTC.hh new file mode 100644 index 0000000..a5ecadf --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QTC.hh @@ -0,0 +1,43 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QTC_HH +#define QTC_HH + +#include + +// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC calls in any code that +// includes this file, but QTC will still be built into the library. That way, it is possible to +// build and package qpdf with QPDF_DISABLE_QTC while still making QTC::TC available to end users. + +namespace QTC +{ + QPDF_DLL + void TC_real(char const* const scope, char const* const ccase, int n = 0); + + inline void + TC(char const* const scope, char const* const ccase, int n = 0) + { +#ifndef QPDF_DISABLE_QTC + TC_real(scope, ccase, n); +#endif // QPDF_DISABLE_QTC + } +}; // namespace QTC + +#endif // QTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QUtil.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QUtil.hh new file mode 100644 index 0000000..18d6083 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/QUtil.hh @@ -0,0 +1,512 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QUTIL_HH +#define QUTIL_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RandomDataProvider; +class Pipeline; + +namespace QUtil +{ + // This is a collection of useful utility functions that don't really go anywhere else. + QPDF_DLL + std::string int_to_string(long long, int length = 0); + QPDF_DLL + std::string uint_to_string(unsigned long long, int length = 0); + QPDF_DLL + std::string int_to_string_base(long long, int base, int length = 0); + QPDF_DLL + std::string uint_to_string_base(unsigned long long, int base, int length = 0); + QPDF_DLL + std::string double_to_string(double, int decimal_places = 0, bool trim_trailing_zeroes = true); + + // These string to number methods throw std::runtime_error on underflow/overflow. + QPDF_DLL + long long string_to_ll(char const* str); + QPDF_DLL + int string_to_int(char const* str); + QPDF_DLL + unsigned long long string_to_ull(char const* str); + QPDF_DLL + unsigned int string_to_uint(char const* str); + + // Returns true if this exactly represents a long long. The determination is made by converting + // the string to a long long, then converting the result back to a string, and then comparing + // that result with the original string. + QPDF_DLL + bool is_long_long(char const* str); + + // Pipeline's write method wants unsigned char*, but we often have some other type of string. + // These methods do combinations of const_cast and reinterpret_cast to give us an unsigned + // char*. They should only be used when it is known that it is safe. None of the pipelines in + // qpdf modify the data passed to them, so within qpdf, it should always be safe. + QPDF_DLL + unsigned char* unsigned_char_pointer(std::string const& str); + QPDF_DLL + unsigned char* unsigned_char_pointer(char const* str); + + // Throw QPDFSystemError, which is derived from std::runtime_error, with a string formed by + // appending to "description: " the standard string corresponding to the current value of errno. + // You can retrieve the value of errno by calling getErrno() on the QPDFSystemError. Prior to + // qpdf 8.2.0, this method threw system::runtime_error directly, but since QPDFSystemError is + // derived from system::runtime_error, old code that specifically catches std::runtime_error + // will still work. + QPDF_DLL + void throw_system_error(std::string const& description); + + // The status argument is assumed to be the return value of a standard library call that sets + // errno when it fails. If status is -1, convert the current value of errno to a + // std::runtime_error that includes the standard error string. Otherwise, return status. + QPDF_DLL + int os_wrapper(std::string const& description, int status); + + // If the open fails, throws std::runtime_error. Otherwise, the FILE* is returned. The filename + // should be UTF-8 encoded, even on Windows. It will be converted as needed on Windows. + QPDF_DLL + FILE* safe_fopen(char const* filename, char const* mode); + + // The FILE* argument is assumed to be the return of fopen. If null, throw std::runtime_error. + // Otherwise, return the FILE* argument. + QPDF_DLL + FILE* fopen_wrapper(std::string const&, FILE*); + + // This is a little class to help with automatic closing files. You can do something like + // + // QUtil::FileCloser fc(QUtil::safe_fopen(filename, "rb")); + // + // and then use fc.f to the file. Be sure to actually declare a variable of type FileCloser. + // Using it as a temporary won't work because it will close the file as soon as it goes out of + // scope. + class FileCloser + { + public: + FileCloser(FILE* f) : + f(f) + { + } + + ~FileCloser() + { + if (f) { + fclose(f); + f = nullptr; + } + } + + FILE* f; + }; + + // Attempt to open the file read only and then close again + QPDF_DLL + bool file_can_be_opened(char const* filename); + + // Wrap around off_t versions of fseek and ftell if available + QPDF_DLL + int seek(FILE* stream, qpdf_offset_t offset, int whence); + QPDF_DLL + qpdf_offset_t tell(FILE* stream); + + QPDF_DLL + bool same_file(char const* name1, char const* name2); + + QPDF_DLL + void remove_file(char const* path); + + // rename_file will overwrite newname if it exists + QPDF_DLL + void rename_file(char const* oldname, char const* newname); + + // Write the contents of filename as a binary file to the pipeline. + QPDF_DLL + void pipe_file(char const* filename, Pipeline* p); + + // Return a function that will send the contents of the given file through the given pipeline as + // binary data. + QPDF_DLL + std::function file_provider(std::string const& filename); + + // Return the last path element. On Windows, either / or \ are path separators. Otherwise, only + // / is a path separator. Strip any trailing path separators. Then, if any path separators + // remain, return everything after the last path separator. Otherwise, return the whole string. + // As a special case, if a string consists entirely of path separators, the first character is + // returned. + QPDF_DLL + std::string path_basename(std::string const& filename); + + // Returns a dynamically allocated copy of a string that the caller has to delete with delete[]. + QPDF_DLL + char* copy_string(std::string const&); + + // Returns a shared_ptr with the correct deleter. + QPDF_DLL + std::shared_ptr make_shared_cstr(std::string const&); + + // Copy string as a unique_ptr to an array. + QPDF_DLL + std::unique_ptr make_unique_cstr(std::string const&); + + // Create a shared pointer to an array. From c++20, std::make_shared(n) does this. + template + std::shared_ptr + make_shared_array(size_t n) + { + return std::shared_ptr(new T[n], std::default_delete()); + } + + // Returns lower-case hex-encoded version of the string, treating each character in the input + // string as unsigned. The output string will be twice as long as the input string. + QPDF_DLL + std::string hex_encode(std::string const&); + + // Returns lower-case hex-encoded version of the char including a leading "#". + QPDF_DLL + std::string hex_encode_char(char); + + // Returns a string that is the result of decoding the input string. The input string may + // consist of mixed case hexadecimal digits. Any characters that are not hexadecimal digits will + // be silently ignored. If there are an odd number of hexadecimal digits, a trailing 0 will be + // assumed. + QPDF_DLL + std::string hex_decode(std::string const&); + + // Decode a single hex digit into a char in the range 0 <= char < 16. Return a char >= 16 if + // digit is not a valid hex digit. + QPDF_DLL + char hex_decode_char(char digit); + + // Set stdin, stdout to binary mode + QPDF_DLL + void binary_stdout(); + QPDF_DLL + void binary_stdin(); + // Set stdout to line buffered + QPDF_DLL + void setLineBuf(FILE*); + + // May modify argv0 + QPDF_DLL + char* getWhoami(char* argv0); + + // Get the value of an environment variable in a portable fashion. Returns true iff the variable + // is defined. If `value' is non-null, initializes it with the value of the variable. + QPDF_DLL + bool get_env(std::string const& var, std::string* value = nullptr); + + QPDF_DLL + time_t get_current_time(); + + // Portable structure representing a point in time with second granularity and time zone offset. + struct QPDFTime + { + QPDFTime() = default; + QPDFTime(QPDFTime const&) = default; + QPDFTime& operator=(QPDFTime const&) = default; + QPDFTime(int year, int month, int day, int hour, int minute, int second, int tz_delta) : + year(year), + month(month), + day(day), + hour(hour), + minute(minute), + second(second), + tz_delta(tz_delta) + { + } + int year; // actual year, no 1900 stuff + int month; // 1--12 + int day; // 1--31 + int hour; + int minute; + int second; + int tz_delta; // minutes before UTC + }; + + QPDF_DLL + QPDFTime get_current_qpdf_time(); + + // Convert a QPDFTime structure to a PDF timestamp string, which is "D:yyyymmddhhmmss" where + // is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone offset. may also be + // omitted. + // Examples: "D:20210207161528-05'00'", "D:20210207211528Z", "D:20210207211528". + // See get_current_qpdf_time and the QPDFTime structure above. + QPDF_DLL + std::string qpdf_time_to_pdf_time(QPDFTime const&); + + // Convert QPDFTime to a second-granularity ISO-8601 timestamp. + QPDF_DLL + std::string qpdf_time_to_iso8601(QPDFTime const&); + + // Convert a PDF timestamp string to a QPDFTime. If syntactically valid, return true and fill in + // qtm. If not valid, return false, and do not modify qtm. If qtm is null, just check the + // validity of the string. + QPDF_DLL + bool pdf_time_to_qpdf_time(std::string const&, QPDFTime* qtm = nullptr); + + // Convert PDF timestamp to a second-granularity ISO-8601 timestamp. If syntactically valid, + // return true and initialize iso8601. Otherwise, return false. + bool pdf_time_to_iso8601(std::string const& pdf_time, std::string& iso8601); + + // Return a string containing the byte representation of the UTF-8 encoding for the unicode + // value passed in. + QPDF_DLL + std::string toUTF8(unsigned long uval); + + // Return a string containing the byte representation of the UTF-16 big-endian encoding for the + // unicode value passed in. Unrepresentable code points are converted to U+FFFD. + QPDF_DLL + std::string toUTF16(unsigned long uval); + + // If utf8_val.at(pos) points to the beginning of a valid UTF-8-encoded character, return the + // codepoint of the character and set error to false. Otherwise, return 0xfffd and set error to + // true. In all cases, pos is advanced to the next position that may begin a valid character. + // When the string has been consumed, pos will be set to the string length. It is an error to + // pass a value of pos that is greater than or equal to the length of the string. + QPDF_DLL + unsigned long get_next_utf8_codepoint(std::string const& utf8_val, size_t& pos, bool& error); + + // Test whether this is a UTF-16 string. This is indicated by first two bytes being 0xFE 0xFF + // (big-endian) or 0xFF 0xFE (little-endian), each of which is the encoding of U+FEFF, the + // Unicode marker. Starting in qpdf 10.6.2, this detects little-endian as well as big-endian. + // Even though the PDF spec doesn't allow little-endian, most readers seem to accept it. + QPDF_DLL + bool is_utf16(std::string const&); + + // Test whether this is an explicit UTF-8 string as allowed by the PDF 2.0 spec. This is + // indicated by first three bytes being 0xEF 0xBB 0xBF, which is the UTF-8 encoding of U+FEFF. + QPDF_DLL + bool is_explicit_utf8(std::string const&); + + // Convert a UTF-8 encoded string to UTF-16 big-endian. Unrepresentable code points are + // converted to U+FFFD. + QPDF_DLL + std::string utf8_to_utf16(std::string const& utf8); + + // Convert a UTF-8 encoded string to the specified single-byte encoding system by replacing all + // unsupported characters with the given unknown_char. + QPDF_DLL + std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?'); + + // These versions return true if the conversion was successful and false if any unrepresentable + // characters were found and had to be substituted with the unknown character. + QPDF_DLL + bool utf8_to_ascii(std::string const& utf8, std::string& ascii, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_win_ansi(std::string const& utf8, std::string& win, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_mac_roman(std::string const& utf8, std::string& mac, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_pdf_doc(std::string const& utf8, std::string& pdfdoc, char unknown_char = '?'); + + // Convert a UTF-16 encoded string to UTF-8. Unrepresentable code + // points are converted to U+FFFD. + QPDF_DLL + std::string utf16_to_utf8(std::string const& utf16); + + // Convert from the specified single-byte encoding system to UTF-8. There is no ascii_to_utf8 + // because all ASCII strings are already valid UTF-8. + QPDF_DLL + std::string win_ansi_to_utf8(std::string const& win); + QPDF_DLL + std::string mac_roman_to_utf8(std::string const& mac); + QPDF_DLL + std::string pdf_doc_to_utf8(std::string const& pdfdoc); + + // Analyze a string for encoding. We can't tell the difference between any single-byte + // encodings, and we can't tell for sure whether a string that happens to be valid UTF-8 isn't a + // different encoding, but we can at least tell a few things to help us guess. If there are no + // characters with the high bit set, has_8bit_chars is false, and the other values are also + // false, even though ASCII strings are valid UTF-8. is_valid_utf8 means that the string is + // non-trivially valid UTF-8. Although the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and + // just about everything else) accepts UTF-16LE (as of 10.6.2). + QPDF_DLL + void analyze_encoding( + std::string const& str, bool& has_8bit_chars, bool& is_valid_utf8, bool& is_utf16); + + // Try to compensate for previously incorrectly encoded strings. We want to compensate for the + // following errors: + // + // * The string was supposed to be UTF-8 but was one of the single-byte encodings + // * The string was supposed to be PDF Doc but was either UTF-8 or one of the other single-byte + // encodings + // + // The returned vector always contains the original string first, and then it contains what the + // correct string would be in the event that the original string was the result of any of the + // above errors. + // + // This method is useful for attempting to recover a password that may have been previously + // incorrectly encoded. For example, the password was supposed to be UTF-8 but the previous + // application used a password encoded in WinAnsi, or if the previous password was supposed to + // be PDFDoc but was actually given as UTF-8 or WinAnsi, this method would find the correct + // password. + QPDF_DLL + std::vector possible_repaired_encodings(std::string); + + // Return a cryptographically secure random number. + QPDF_DLL + long random(); + + // Initialize a buffer with cryptographically secure random bytes. + QPDF_DLL + void initializeWithRandomBytes(unsigned char* data, size_t len); + + // Supply a random data provider. Starting in qpdf 10.0.0, qpdf uses the crypto provider as its + // source of random numbers. If you are using the native crypto provider, then qpdf will either + // use the operating system's secure random number source or, only if enabled at build time, an + // insecure random source from stdlib. The caller is responsible for managing the memory for the + // RandomDataProvider. This method modifies a static variable. If you are providing your own + // random data provider, you should call this at the beginning of your program before creating + // any QPDF objects. Passing a null to this method will reset the library back to its default + // random data provider. + QPDF_DLL + void setRandomDataProvider(RandomDataProvider*); + + // This returns the random data provider that would be used the next time qpdf needs random + // data. It will never return null. If no random data provider has been provided and the + // library was not compiled with any random data provider available, an exception will be + // thrown. + QPDF_DLL + RandomDataProvider* getRandomDataProvider(); + + // Filename is UTF-8 encoded, even on Windows, as described in the comments for safe_fopen. + QPDF_DLL + std::list read_lines_from_file(char const* filename, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(std::istream&, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(FILE*, bool preserve_eol = false); + QPDF_DLL + void read_lines_from_file( + std::function next_char, + std::list& lines, + bool preserve_eol = false); + + QPDF_DLL + void read_file_into_memory(char const* filename, std::shared_ptr& file_buf, size_t& size); + + QPDF_DLL + std::string read_file_into_string(char const* filename); + QPDF_DLL + std::string read_file_into_string(FILE* f, std::string_view filename = ""); + + // This used to be called strcasecmp, but that is a macro on some platforms, so we have to give + // it a name that is not likely to be a macro anywhere. + QPDF_DLL + int str_compare_nocase(char const*, char const*); + + // These routines help the tokenizer recognize certain character classes without using ctype, + // which we avoid because of locale considerations. + QPDF_DLL + bool is_hex_digit(char); + + QPDF_DLL + bool is_space(char); + + QPDF_DLL + bool is_digit(char); + + QPDF_DLL + bool is_number(char const*); + + /// @brief Handles the result code from qpdf functions. + /// + /// **For qpdf internal use only - not part of the public API** + /// @par + /// Depending on the result code, either continues execution or throws an + /// exception in case of an invalid parameter. + /// + /// @param result The result code of type qpdf_result_e, indicating success or failure status. + /// @param context A string describing the context where this function is invoked, used for + /// error reporting if an exception is thrown. + /// + /// @throws std::logic_error If the result code is `qpdf_bad_parameter`, indicating an invalid + /// parameter was supplied to a function. The exception message will + /// include the provided context for easier debugging. + /// + /// @since 12.3 + QPDF_DLL + void handle_result_code(qpdf_result_e result, std::string_view context); + + // This method parses the numeric range syntax used by the qpdf command-line tool. May throw + // std::runtime_error. A numeric range is as comma-separated list of groups. A group may be a + // number specification or a range of number specifications separated by a dash. A number + // specification may be one of the following (where is a number): + // * -- the numeric value of n + // * z -- the value of the `max` parameter + // * r -- represents max + 1 - ( from the end) + // + // If the group is two number specifications separated by a dash, it represents the range of + // numbers from the first to the second, inclusive. If the first is greater than the second, the + // numbers are descending. + // + // From qpdf 11.7.1: if a group starts with `x`, its members are excluded from the previous + // group that didn't start with `x1. + // + // Example: with max of 15, the range "4-10,x7-9,12-8,xr5" is 4, 5, 6, 10, 12, 10, 9, 8. This is + // 4 through 10 inclusive without 7 through 9 inclusive followed by 12 to 8 inclusive + // (descending) without 11 (the fifth value counting backwards from 15). For more information + // and additional examples, see the "Page Ranges" section in the manual. + QPDF_DLL + std::vector parse_numrange(char const* range, int max); + +#ifndef QPDF_NO_WCHAR_T + // If you are building qpdf on a stripped down system that doesn't have wchar_t, such as may be + // the case in some embedded environments, you may define QPDF_NO_WCHAR_T in your build. This + // symbol is never defined automatically. Search for wchar_t in qpdf's top-level README.md file + // for details. + + // Take an argv array consisting of wchar_t, as when wmain is invoked, convert all UTF-16 + // encoded strings to UTF-8, and call another main. + QPDF_DLL + int call_main_from_wmain(int argc, wchar_t* argv[], std::function realmain); + QPDF_DLL + int call_main_from_wmain( + int argc, + wchar_t const* const argv[], + std::function realmain); +#endif // QPDF_NO_WCHAR_T + + // Try to return the maximum amount of memory allocated by the current process and its threads. + // Return 0 if unable to determine. This is Linux-specific and not implemented to be completely + // reliable. It is used during development for performance testing to detect changes that may + // significantly change memory usage. It is not recommended for use for other purposes. + QPDF_DLL + size_t get_max_memory_usage(); +}; // namespace QUtil + +#endif // QUTIL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/RandomDataProvider.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/RandomDataProvider.hh new file mode 100644 index 0000000..c929f0f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/RandomDataProvider.hh @@ -0,0 +1,44 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef RANDOMDATAPROVIDER_HH +#define RANDOMDATAPROVIDER_HH + +#include +#include // for size_t + +class QPDF_DLL_CLASS RandomDataProvider +{ + public: + virtual ~RandomDataProvider() = default; + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + protected: + QPDF_DLL_PRIVATE + RandomDataProvider() = default; + + private: + RandomDataProvider(RandomDataProvider const&) = delete; + RandomDataProvider& operator=(RandomDataProvider const&) = delete; +}; + +#endif // RANDOMDATAPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Types.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Types.h new file mode 100644 index 0000000..015cd22 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/Types.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFTYPES_H +#define QPDFTYPES_H + +/* Provide an offset type that should be as big as off_t on just about + * any system. If your compiler doesn't support C99 (or at least the + * "long long" type), then you may have to modify this definition. + */ + +typedef long long int qpdf_offset_t; + +#endif /* QPDFTYPES_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_att.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_att.hh new file mode 100644 index 0000000..ea85419 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_att.hh @@ -0,0 +1,14 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL AttConfig* replace(); +QPDF_DLL AttConfig* key(std::string const& parameter); +QPDF_DLL AttConfig* filename(std::string const& parameter); +QPDF_DLL AttConfig* creationdate(std::string const& parameter); +QPDF_DLL AttConfig* moddate(std::string const& parameter); +QPDF_DLL AttConfig* mimetype(std::string const& parameter); +QPDF_DLL AttConfig* description(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_copy_att.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_copy_att.hh new file mode 100644 index 0000000..764a5ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_copy_att.hh @@ -0,0 +1,9 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL CopyAttConfig* prefix(std::string const& parameter); +QPDF_DLL CopyAttConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_enc.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_enc.hh new file mode 100644 index 0000000..ed4d071 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_enc.hh @@ -0,0 +1,20 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL EncConfig* extract(std::string const& parameter); +QPDF_DLL EncConfig* annotate(std::string const& parameter); +QPDF_DLL EncConfig* print(std::string const& parameter); +QPDF_DLL EncConfig* modify(std::string const& parameter); +QPDF_DLL EncConfig* cleartextMetadata(); +QPDF_DLL EncConfig* forceV4(); +QPDF_DLL EncConfig* accessibility(std::string const& parameter); +QPDF_DLL EncConfig* assemble(std::string const& parameter); +QPDF_DLL EncConfig* form(std::string const& parameter); +QPDF_DLL EncConfig* modifyOther(std::string const& parameter); +QPDF_DLL EncConfig* useAes(std::string const& parameter); +QPDF_DLL EncConfig* forceR5(); +QPDF_DLL EncConfig* allowInsecure(); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_global.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_global.hh new file mode 100644 index 0000000..7f8758b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_global.hh @@ -0,0 +1,13 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL GlobalConfig* noDefaultLimits(); +QPDF_DLL GlobalConfig* parserMaxContainerSize(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxContainerSizeDamaged(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxErrors(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxNesting(std::string const& parameter); +QPDF_DLL GlobalConfig* maxStreamFilters(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_limits.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_limits.hh new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_main.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_main.hh new file mode 100644 index 0000000..0ed4f64 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_main.hh @@ -0,0 +1,97 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL Config* allowWeakCrypto(); +QPDF_DLL Config* check(); +QPDF_DLL Config* checkLinearization(); +QPDF_DLL Config* coalesceContents(); +QPDF_DLL Config* decrypt(); +QPDF_DLL Config* deterministicId(); +QPDF_DLL Config* externalizeInlineImages(); +QPDF_DLL Config* filteredStreamData(); +QPDF_DLL Config* flattenRotation(); +QPDF_DLL Config* generateAppearances(); +QPDF_DLL Config* ignoreXrefStreams(); +QPDF_DLL Config* isEncrypted(); +QPDF_DLL Config* jsonInput(); +QPDF_DLL Config* keepInlineImages(); +QPDF_DLL Config* linearize(); +QPDF_DLL Config* listAttachments(); +QPDF_DLL Config* newlineBeforeEndstream(); +QPDF_DLL Config* noOriginalObjectIds(); +QPDF_DLL Config* noWarn(); +QPDF_DLL Config* optimizeImages(); +QPDF_DLL Config* passwordIsHexKey(); +QPDF_DLL Config* preserveUnreferenced(); +QPDF_DLL Config* preserveUnreferencedResources(); +QPDF_DLL Config* progress(); +QPDF_DLL Config* qdf(); +QPDF_DLL Config* rawStreamData(); +QPDF_DLL Config* recompressFlate(); +QPDF_DLL Config* removeAcroform(); +QPDF_DLL Config* removeInfo(); +QPDF_DLL Config* removeMetadata(); +QPDF_DLL Config* removePageLabels(); +QPDF_DLL Config* removeStructure(); +QPDF_DLL Config* reportMemoryUsage(); +QPDF_DLL Config* requiresPassword(); +QPDF_DLL Config* removeRestrictions(); +QPDF_DLL Config* showEncryption(); +QPDF_DLL Config* showEncryptionKey(); +QPDF_DLL Config* showLinearization(); +QPDF_DLL Config* showNpages(); +QPDF_DLL Config* showPages(); +QPDF_DLL Config* showXref(); +QPDF_DLL Config* staticAesIv(); +QPDF_DLL Config* staticId(); +QPDF_DLL Config* suppressPasswordRecovery(); +QPDF_DLL Config* suppressRecovery(); +QPDF_DLL Config* testJsonSchema(); +QPDF_DLL Config* verbose(); +QPDF_DLL Config* warningExit0(); +QPDF_DLL Config* withImages(); +QPDF_DLL Config* compressionLevel(std::string const& parameter); +QPDF_DLL Config* jpegQuality(std::string const& parameter); +QPDF_DLL Config* copyEncryption(std::string const& parameter); +QPDF_DLL Config* encryptionFilePassword(std::string const& parameter); +QPDF_DLL Config* forceVersion(std::string const& parameter); +QPDF_DLL Config* iiMinBytes(std::string const& parameter); +QPDF_DLL Config* jobJsonFile(std::string const& parameter); +QPDF_DLL Config* jsonObject(std::string const& parameter); +QPDF_DLL Config* keepFilesOpenThreshold(std::string const& parameter); +QPDF_DLL Config* linearizePass1(std::string const& parameter); +QPDF_DLL Config* minVersion(std::string const& parameter); +QPDF_DLL Config* oiMinArea(std::string const& parameter); +QPDF_DLL Config* oiMinHeight(std::string const& parameter); +QPDF_DLL Config* oiMinWidth(std::string const& parameter); +QPDF_DLL Config* password(std::string const& parameter); +QPDF_DLL Config* passwordFile(std::string const& parameter); +QPDF_DLL Config* removeAttachment(std::string const& parameter); +QPDF_DLL Config* rotate(std::string const& parameter); +QPDF_DLL Config* showAttachment(std::string const& parameter); +QPDF_DLL Config* showObject(std::string const& parameter); +QPDF_DLL Config* jsonStreamPrefix(std::string const& parameter); +QPDF_DLL Config* updateFromJson(std::string const& parameter); +QPDF_DLL Config* collate(std::string const& parameter); +QPDF_DLL Config* collate(); +QPDF_DLL Config* splitPages(std::string const& parameter); +QPDF_DLL Config* splitPages(); +QPDF_DLL Config* compressStreams(std::string const& parameter); +QPDF_DLL Config* decodeLevel(std::string const& parameter); +QPDF_DLL Config* flattenAnnotations(std::string const& parameter); +QPDF_DLL Config* jsonKey(std::string const& parameter); +QPDF_DLL Config* jsonStreamData(std::string const& parameter); +QPDF_DLL Config* keepFilesOpen(std::string const& parameter); +QPDF_DLL Config* normalizeContent(std::string const& parameter); +QPDF_DLL Config* objectStreams(std::string const& parameter); +QPDF_DLL Config* passwordMode(std::string const& parameter); +QPDF_DLL Config* removeUnreferencedResources(std::string const& parameter); +QPDF_DLL Config* streamData(std::string const& parameter); +QPDF_DLL Config* json(std::string const& parameter); +QPDF_DLL Config* json(); +QPDF_DLL Config* jsonOutput(std::string const& parameter); +QPDF_DLL Config* jsonOutput(); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_pages.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_pages.hh new file mode 100644 index 0000000..75b0ae5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_pages.hh @@ -0,0 +1,10 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL PagesConfig* file(std::string const& parameter); +QPDF_DLL PagesConfig* range(std::string const& parameter); +QPDF_DLL PagesConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_set_page_labels.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_set_page_labels.hh new file mode 100644 index 0000000..b816d29 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_set_page_labels.hh @@ -0,0 +1,7 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_uo.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_uo.hh new file mode 100644 index 0000000..547ecf3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/auto_job_c_uo.hh @@ -0,0 +1,12 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL UOConfig* file(std::string const& parameter); +QPDF_DLL UOConfig* to(std::string const& parameter); +QPDF_DLL UOConfig* from(std::string const& parameter); +QPDF_DLL UOConfig* repeat(std::string const& parameter); +QPDF_DLL UOConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/global.hh b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/global.hh new file mode 100644 index 0000000..b99ee31 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/global.hh @@ -0,0 +1,264 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef GLOBAL_HH +#define GLOBAL_HH + +#include + +#include +#include + +#include + +namespace qpdf::global +{ + /// Helper function to translate result codes into C++ exceptions - for qpdf internal use only. + inline void + handle_result(qpdf_result_e result) + { + if (result != qpdf_r_ok) { + QUtil::handle_result_code(result, "qpdf::global"); + } + } + + /// Helper function to wrap calls to qpdf_global_get_uint32 - for qpdf internal use only. + inline uint32_t + get_uint32(qpdf_param_e param) + { + uint32_t value; + handle_result(qpdf_global_get_uint32(param, &value)); + return value; + } + + /// Helper function to wrap calls to qpdf_global_set_uint32 - for qpdf internal use only. + inline void + set_uint32(qpdf_param_e param, uint32_t value) + { + handle_result(qpdf_global_set_uint32(param, value)); + } + + /// @brief Retrieves the number of limit errors. + /// + /// Returns the number of times a global limit was exceeded. This item is read only. + /// + /// @return The number of limit errors. + /// + /// @since 12.3 + uint32_t inline limit_errors() + { + return get_uint32(qpdf_p_limit_errors); + } + + namespace options + { + /// @brief Retrieves whether inspection mode is set. + /// + /// @return True if inspection mode is set. + /// + /// @since 12.3 + bool inline inspection_mode() + { + return get_uint32(qpdf_p_inspection_mode) != 0; + } + + /// @brief Set inspection mode if `true` is passed. + /// + /// This function enables restrictive inspection mode if `true` is passed. Inspection mode + /// must be enabled before a QPDF object is created. By default inspection mode is off. + /// Calling `inspection_mode(false)` is not supported and currently is a no-op. + /// + /// @param value A boolean indicating whether to enable (true) inspection mode. + /// + /// @since 12.3 + void inline inspection_mode(bool value) + { + set_uint32(qpdf_p_inspection_mode, value ? QPDF_TRUE : QPDF_FALSE); + } + + /// @brief Retrieves whether default limits are enabled. + /// + /// @return True if default limits are enabled. + /// + /// @since 12.3 + bool inline default_limits() + { + return get_uint32(qpdf_p_default_limits) != 0; + } + + /// @brief Disable all optional default limits if `false` is passed. + /// + /// This function disables all optional default limits if `false` is passed. Once default + /// values have been disabled they cannot be re-enabled. Passing `true` has no effect. This + /// function will leave any limits that have been explicitly set unchanged. Some limits, + /// such as limits imposed to avoid stack overflows, cannot be disabled but can be changed. + /// + /// @param value A boolean indicating whether to disable (false) the default limits. + /// + /// @since 12.3 + void inline default_limits(bool value) + { + set_uint32(qpdf_p_default_limits, value ? QPDF_TRUE : QPDF_FALSE); + } + + } // namespace options + + namespace limits + { + /// @brief Retrieves the maximum nesting level while parsing objects. + /// + /// @return The maximum nesting level while parsing objects. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + uint32_t inline parser_max_nesting() + { + return get_uint32(qpdf_p_parser_max_nesting); + } + + /// @brief Sets the maximum nesting level while parsing objects. + /// + /// @param value The maximum nesting level to set. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + void inline parser_max_nesting(uint32_t value) + { + set_uint32(qpdf_p_parser_max_nesting, value); + } + + /// @brief Retrieves the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @return The maximum number of errors allowed while parsing objects. + /// + /// @since 12.3 + uint32_t inline parser_max_errors() + { + return get_uint32(qpdf_p_parser_max_errors); + } + + /// Sets the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @param value The maximum number of errors allowed while parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_errors(uint32_t value) + { + set_uint32(qpdf_p_parser_max_errors, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size() + { + return get_uint32(qpdf_p_parser_max_container_size); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing objects. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing xref streams. The default limit is 5,000. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size_damaged() + { + return get_uint32(qpdf_p_parser_max_container_size_damaged); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing trailer dictionaries and xref streams. The + /// default limit is 5,000. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size_damaged(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size_damaged, value); + } + + /// @brief Retrieves the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @return The maximum number of filters allowed when filtering streams. + /// + /// @since 12.3 + uint32_t inline max_stream_filters() + { + return get_uint32(qpdf_p_max_stream_filters); + } + + /// @brief Sets the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @param value The maximum number of filters allowed when filtering streams to set. + /// + /// @since 12.3 + void inline max_stream_filters(uint32_t value) + { + set_uint32(qpdf_p_max_stream_filters, value); + } + } // namespace limits + +} // namespace qpdf::global + +#endif // GLOBAL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdf-c.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdf-c.h new file mode 100644 index 0000000..c602f9f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdf-c.h @@ -0,0 +1,1070 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDF_C_H +#define QPDF_C_H + +/* + * This file defines a basic "C" API for qpdf. It provides access to a subset of the QPDF library's + * capabilities to make them accessible to callers who can't handle calling C++ functions or working + * with C++ classes. This may be especially useful to Windows users who are accessing the qpdf DLL + * directly or to other people programming in non-C/C++ languages that can call C code but not C++ + * code. Starting with qpdf 11.7, it is possible to write your own `extern "C"` functions that + * interoperate with the C API. + * + * There are several things to keep in mind when using the C API. + * + * Error handling is tricky because the underlying C++ API uses exception handling. See "ERROR + * HANDLING" below for a detailed explanation. + * + * The C API is not as rich as the C++ API. For many operations, you must use the C++ API. The C + * API is primarily useful for doing basic transformations on PDF files similar to what you + * might do with the qpdf command-line tool. You can write your own `extern "C"` functions in + * C++ that interoperate with the C API by using qpdf_c_get_qpdf and qpdf_c_wrap which were + * introduced in qpdf 11.7.0. + * + * These functions store their state in a qpdf_data object. Individual instances of qpdf_data + * are not thread-safe: although you may access different qpdf_data objects from different + * threads, you may not access one qpdf_data simultaneously from multiple threads. + * + * All dynamic memory, except for that of the qpdf_data object itself, is managed by the library + * unless otherwise noted. You must create a qpdf_data object using qpdf_init and free it using + * qpdf_cleanup. + * + * Many functions return char*. In all cases, the char* values returned are pointers to data + * inside the qpdf_data object. As such, they are always freed by qpdf_cleanup. In most cases, + * strings returned by functions here may be invalidated by subsequent function calls, sometimes + * even to different functions. If you want a string to last past the next qpdf call or after a + * call to qpdf_cleanup, you should make a copy of it. + * + * Since it is possible for a PDF string to contain null characters, a function that returns + * data originating from a PDF string may also contain null characters. To handle that case, you + * call qpdf_get_last_string_length() to get the length of whatever string was just returned. + * See STRING FUNCTIONS below. + * + * Most functions defined here have obvious counterparts that are methods to either QPDF or + * QPDFWriter. Please see comments in QPDF.hh and QPDFWriter.hh for details on their use. In + * order to avoid duplication of information, comments here focus primarily on differences + * between the C and C++ API. + */ + +/* ERROR HANDLING -- changed in qpdf 10.5 */ + +/* SUMMARY: The only way to know whether a function that does not return an error code has + * encountered an error is to call qpdf_has_error after each function. You can do this even for + * functions that do return error codes. You can also call qpdf_silence_errors to prevent qpdf from + * writing these errors to stderr. + * + * DETAILS: + * + * The data type underlying qpdf_data maintains a list of warnings and a single error. To retrieve + * warnings, call qpdf_next_warning while qpdf_more_warnings is true. To retrieve the error, call + * qpdf_get_error when qpdf_has_error is true. + * + * There are several things that are important to understand. + * + * Some functions return an error code. The value of the error code is made up of a bitwise-OR of + * QPDF_WARNINGS and QPDF_ERRORS. The QPDF_ERRORS bit is set if there was an error during the *most + * recent call* to the API. The QPDF_WARNINGS bit is set if there are any warnings that have not yet + * been retrieved by calling qpdf_more_warnings. It is possible for both its or neither bit to be + * set. + * + * The expected mode of operation is to go through a series of operations, checking for errors after + * each call, but only checking for warnings at the end. This is similar to how it works in the C++ + * API where warnings are handled in exactly this way but errors result in exceptions being thrown. + * However, in both the C and C++ API, it is possible to check for and handle warnings as they + * arise. + * + * Some functions return values (or void) rather than an error code. This is especially true with + * the object handling functions. Those functions can still generate errors. To handle errors in + * those cases, you should explicitly call qpdf_has_error(). Note that, if you want to avoid the + * inconsistencies in the interface, you can always check for error conditions in this way rather + * than looking at status return codes. + * + * Prior to qpdf 10.5, if one of the functions that does not return an error code encountered an + * exception, it would cause the entire program to crash. Starting in qpdf 10.5, the default + * response to an error condition in these situations is to print the error to standard error, issue + * exactly one warning indicating that such an error occurred, and return a sensible fallback value + * (0 for numbers, QPDF_FALSE for booleans, "" for strings, or a null or uninitialized object + * handle). This is better than the old behavior but still undesirable as the best option is to + * explicitly check for error conditions. + * + * To prevent qpdf from writing error messages to stderr in this way, you can call + * qpdf_silence_errors(). This signals to the qpdf library that you intend to check the error codes + * yourself. + * + * If you encounter a situation where an exception from the C++ code is not properly converted to an + * error as described above, it is a bug in qpdf, which should be reported at + * https://github.com/qpdf/qpdf/issues/new. + */ + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _qpdf_data* qpdf_data; + typedef struct _qpdf_error* qpdf_error; + + /* Many functions return an integer error code. Codes are defined below. See comments at the + * top of the file for details. Note that the values below can be logically orred together. + */ + typedef int QPDF_ERROR_CODE; +#define QPDF_SUCCESS 0 +#define QPDF_WARNINGS 1 << 0 +#define QPDF_ERRORS 1 << 1 + + typedef int QPDF_BOOL; +#define QPDF_TRUE 1 +#define QPDF_FALSE 0 + + /* From qpdf 10.5: call this method to signal to the library that you are explicitly handling + * errors from functions that don't return error codes. Otherwise, the library will print these + * error conditions to stderr and issue a warning. Prior to 10.5, the program would have + * crashed from an unhandled exception. + */ + QPDF_DLL + void qpdf_silence_errors(qpdf_data qpdf); + + /* Returns the version of the qpdf software. This is guaranteed to be a static value. + */ + QPDF_DLL + char const* qpdf_get_qpdf_version(); + + /* Returns dynamically allocated qpdf_data pointer; must be freed by calling qpdf_cleanup. You + * must call qpdf_read, one of the other qpdf_read_* functions, or qpdf_empty_pdf before calling + * any function that would need to operate on the PDF file. + */ + QPDF_DLL + qpdf_data qpdf_init(); + + /* Pass a pointer to the qpdf_data pointer created by qpdf_init to clean up resources. This does + * not include buffers initialized by functions that return stream data but it otherwise + * includes all data associated with the QPDF object or any object handles. + */ + QPDF_DLL + void qpdf_cleanup(qpdf_data* qpdf); + + /* ERROR REPORTING */ + + /* Returns 1 if there is an error condition. The error condition can be retrieved by a single + * call to qpdf_get_error. + */ + QPDF_DLL + QPDF_BOOL qpdf_has_error(qpdf_data qpdf); + + /* Returns the error condition, if any. The return value is a pointer to data that will become + * invalid after the next call to this function, qpdf_next_warning, or qpdf_cleanup. After this + * function is called, qpdf_has_error will return QPDF_FALSE until the next error condition + * occurs. If there is no error condition, this function returns a null pointer. + */ + QPDF_DLL + qpdf_error qpdf_get_error(qpdf_data qpdf); + + /* Returns 1 if there are any unretrieved warnings, and zero otherwise. + */ + QPDF_DLL + QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf); + + /* If there are any warnings, returns a pointer to the next warning. Otherwise returns a null + * pointer. + */ + QPDF_DLL + qpdf_error qpdf_next_warning(qpdf_data qpdf); + + /* Extract fields of the error. */ + + /* Use this function to get a full error message suitable for showing to the user. */ + QPDF_DLL + char const* qpdf_get_error_full_text(qpdf_data q, qpdf_error e); + + /* Use these functions to extract individual fields from the error; see QPDFExc.hh for details. + */ + QPDF_DLL + enum qpdf_error_code_e qpdf_get_error_code(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_filename(qpdf_data q, qpdf_error e); + QPDF_DLL + unsigned long long qpdf_get_error_file_position(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_message_detail(qpdf_data q, qpdf_error e); + + /* By default, warnings are written to stderr. Passing true to this function will prevent + * warnings from being written to stderr. They will still be available by calls to + * qpdf_next_warning. + */ + QPDF_DLL + void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value); + + /* LOG FUNCTIONS */ + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdf_set_logger(qpdf_data qpdf, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdf_get_logger(qpdf_data qpdf); + + /* CHECK FUNCTIONS */ + + /* Attempt to read the entire PDF file to see if there are any errors qpdf can detect. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf); + + /* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */ + + QPDF_DLL + void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value); + + /* PROCESS FUNCTIONS */ + + /* This functions process a PDF or JSON input source. */ + + /* Calling qpdf_read causes processFile to be called in the C++ API. Basic parsing is + * performed, but data from the file is only read as needed. For files without passwords, pass + * a null pointer or an empty string as the password. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_read(qpdf_data qpdf, char const* filename, char const* password); + + /* Calling qpdf_read_memory causes processMemoryFile to be called in the C++ API. Otherwise, it + * behaves in the same way as qpdf_read. The description argument will be used in place of the + * file name in any error or warning messages generated by the library. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_read_memory( + qpdf_data qpdf, + char const* description, + char const* buffer, + unsigned long long size, + char const* password); + + /* Calling qpdf_empty_pdf initializes this qpdf object with an empty PDF, making it possible to + * create a PDF from scratch using the C API. Added in 10.6. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf); + + /* Create a PDF from a JSON file. This calls createFromJSON in the C++ API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_file(qpdf_data qpdf, char const* filename); + + /* Create a PDF from JSON data in a null-terminated string. This calls createFromJSON in the C++ + * API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* JSON UPDATE FUNCTIONS */ + + /* Update a QPDF object from a JSON file or buffer. These functions call updateFromJSON. One of + * the other processing functions has to be called first so that the QPDF object is initialized + * with PDF data. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_file(qpdf_data qpdf, char const* filename); + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* READ FUNCTIONS */ + + /* Read functions below must be called after qpdf_read or any of the other functions that + * process a PDF. */ + + /* + * NOTE: Functions that return char* are returning a pointer to an internal buffer that will be + * reused for each call to a function that returns a char*. You must use or copy the value + * before calling any other qpdf library functions. + */ + + /* Return the version of the PDF file. See warning above about functions that return char*. */ + QPDF_DLL + char const* qpdf_get_pdf_version(qpdf_data qpdf); + + /* Return the extension level of the PDF file. */ + QPDF_DLL + int qpdf_get_pdf_extension_level(qpdf_data qpdf); + + /* Return the user password. If the file is opened using the owner password, the user password + * may be retrieved using this function. If the file is opened using the user password, this + * function will return that user password. See warning above about functions that return + * char*. + */ + QPDF_DLL + char const* qpdf_get_user_password(qpdf_data qpdf); + + /* Return the string value of a key in the document's Info dictionary. The key parameter should + * include the leading slash, e.g. "/Author". If the key is not present or has a non-string + * value, a null pointer is returned. Otherwise, a pointer to an internal buffer is returned. + * See warning above about functions that return char*. + */ + QPDF_DLL + char const* qpdf_get_info_key(qpdf_data qpdf, char const* key); + + /* Set a value in the info dictionary, possibly replacing an existing value. The key must + * include the leading slash (e.g. "/Author"). Passing a null pointer as a value will remove + * the key from the info dictionary. Otherwise, a copy will be made of the string that is + * passed in. + */ + QPDF_DLL + void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value); + + /* Indicate whether the input file is linearized. */ + QPDF_DLL + QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf); + + /* Indicate whether the input file is encrypted. */ + QPDF_DLL + QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf); + + QPDF_DLL + QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf); + + /* JSON WRITE FUNCTIONS */ + + /* This function serializes the PDF to JSON. This calls writeJSON from the C++ API. + * + * - version: the JSON version, currently must be 2 + * - fn: a function that will be called with blocks of JSON data; will be called with data, a + * length, and the value of the udata parameter to this function + * - udata: will be passed as the third argument to fn with each call; use this for your own + * tracking or pass a null pointer if you don't need it + * - For decode_level, json_stream_data, file_prefix, and wanted_objects, see comments in + * QPDF.hh. For this API, wanted_objects should be a null-terminated array of null-terminated + * strings. Pass a null pointer if you want all objects. + */ + + /* Function should return 0 on success. */ + typedef int (*qpdf_write_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + QPDF_ERROR_CODE qpdf_write_json( + qpdf_data qpdf, + int version, + qpdf_write_fn_t fn, + void* udata, + enum qpdf_stream_decode_level_e decode_level, + enum qpdf_json_stream_data_e json_stream_data, + char const* file_prefix, + char const* const* wanted_objects); + + /* WRITE FUNCTIONS */ + + /* Set up for writing. No writing is actually performed until the call to qpdf_write(). + */ + + /* Supply the name of the file to be written and initialize the qpdf_data object to handle + * writing operations. This function also attempts to create the file. The PDF data is not + * written until the call to qpdf_write. qpdf_init_write may be called multiple times for the + * same qpdf_data object. When qpdf_init_write is called, all information from previous calls + * to functions that set write parameters (qpdf_set_linearization, etc.) is lost, so any write + * parameter functions must be called again. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename); + + /* Initialize for writing but indicate that the PDF file should be written to memory. Call + * qpdf_get_buffer_length and qpdf_get_buffer to retrieve the resulting buffer. The memory + * containing the PDF file will be destroyed when qpdf_cleanup is called. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf); + + /* Retrieve the buffer used if the file was written to memory. qpdf_get_buffer returns a null + * pointer if data was not written to memory. The memory is freed when qpdf_cleanup is called + * or if a subsequent call to qpdf_init_write or qpdf_init_write_memory is called. */ + QPDF_DLL + size_t qpdf_get_buffer_length(qpdf_data qpdf); + QPDF_DLL + unsigned char const* qpdf_get_buffer(qpdf_data qpdf); + + QPDF_DLL + void qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode); + + QPDF_DLL + void qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode); + + QPDF_DLL + void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_decode_level(qpdf_data qpdf, enum qpdf_stream_decode_level_e level); + + QPDF_DLL + void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_ID except in test suites to suppress generation of a random /ID. + * See also qpdf_set_deterministic_ID. + */ + QPDF_DLL + void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_aes_IV except in test suites to create predictable AES encrypted + * output. + */ + QPDF_DLL + void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_suppress_original_object_IDs(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value); + + /* The *_insecure functions are identical to the old versions but have been renamed as a an + * alert to the caller that they are insecure. See "Weak Cryptographic" in the manual for + * details. + */ + QPDF_DLL + void qpdf_set_r2_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_print, + QPDF_BOOL allow_modify, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_annotate); + + QPDF_DLL + void qpdf_set_r3_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print); + + QPDF_DLL + void qpdf_set_r4_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata, + QPDF_BOOL use_aes); + + QPDF_DLL + void qpdf_set_r5_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_r6_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void qpdf_set_minimum_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level); + + QPDF_DLL + void qpdf_force_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void + qpdf_force_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level); + + /* During write, your report_progress function will be called with a value between 0 and 100 + * representing the approximate write progress. The data object you pass to + * qpdf_register_progress_reporter will be handed back to your function. This function must be + * called after qpdf_init_write (or qpdf_init_write_memory) and before qpdf_write. The + * registered progress reporter applies only to a single write, so you must call it again if you + * perform a subsequent write with a new writer. + */ + QPDF_DLL + void qpdf_register_progress_reporter( + qpdf_data qpdf, void (*report_progress)(int percent, void* data), void* data); + + /* Do actual write operation. */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf); + + /* Object handling. + * + * These functions take and return a qpdf_oh object handle, which is just an unsigned integer. + * The value 0 is never returned, which makes it usable as an uninitialized value. The handles + * returned by these functions are guaranteed to be unique, i.e. two calls to (the same of + * different) functions will return distinct handles even when they refer to the same object. + * + * Each function below, starting with qpdf_oh, corresponds to a specific method of + * QPDFObjectHandler. For example, qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If + * the C++ method is overloaded, the C function's name will be disambiguated. If the C++ method + * takes optional arguments, the C function will have required arguments in those positions. For + * details about the method, please see comments in QPDFObjectHandle.hh. Comments here only + * explain things that are specific to the "C" API. + * + * Only a fraction of the methods of QPDFObjectHandle are available here. Most of the basic + * methods for creating, accessing, and modifying most types of objects are present. Most of the + * higher-level functions are not implemented. Functions for dealing with content streams as + * well as objects that only exist in content streams (operators and inline images) are mostly + * not provided. + * + * To refer to a specific QPDFObjectHandle, you need a pair consisting of a qpdf_data and a + * qpdf_oh, which is just an index into an internal table of objects. All memory allocated by + * any of these functions is returned when qpdf_cleanup is called. + * + * Regarding memory, the same rules apply as the above functions. Specifically, if a function + * returns a char*, the memory is managed by the library and, unless otherwise specified, is not + * expected to be valid after the next qpdf call. + * + * The qpdf_data object keeps a cache of handles returned by these functions. Once you are + * finished referencing a handle, you can optionally release it. Releasing handles is optional + * since they will all get released by qpdf_cleanup, but it can help to reduce the memory + * footprint of the qpdf_data object to release them when you're done. Releasing a handle does + * not destroy the object. All QPDFObjectHandle objects are deleted when they are no longer + * referenced. Releasing an object handle simply invalidates it. For example, if you create an + * object, add it to an existing dictionary or array, and then release its handle, the object is + * safely part of the dictionary or array. Similarly, any other object handle referring to the + * object remains valid. Explicitly releasing an object handle is essentially the same as + * letting a QPDFObjectHandle go out of scope in the C++ API. + * + * Please see "ERROR HANDLING" above for details on how error conditions are handled. + */ + + /* For examples of using this API, see examples/pdf-c-objects.c */ + + typedef unsigned int qpdf_oh; + + /* Releasing objects -- see comments above. These functions have no equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_oh_release_all(qpdf_data qpdf); + + /* Clone an object handle */ + QPDF_DLL + qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh); + + /* Get trailer and root objects */ + QPDF_DLL + qpdf_oh qpdf_get_trailer(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_get_root(qpdf_data qpdf); + + /* Retrieve and replace indirect objects */ + QPDF_DLL + qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh); + + /* Wrappers around QPDFObjectHandle methods. Be sure to read corresponding comments in + * QPDFObjectHandle.hh to understand what each function does and what kinds of objects it + * applies to. Note that names are to appear in a canonicalized form starting with a leading + * slash and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle.hh + * for details. + */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary_of_type( + qpdf_data qpdf, qpdf_oh oh, char const* type, char const* subtype); + + QPDF_DLL + enum qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str); + + QPDF_DLL + QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value); + + QPDF_DLL + long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value); + QPDF_DLL + int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value); + QPDF_DLL + unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value); + QPDF_DLL + unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value); + + QPDF_DLL + char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value); + + QPDF_DLL + char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + /* Return the length of the last string returned. This enables you to retrieve the entire string + * for cases in which a char* returned by one of the functions below points to a string with + * embedded null characters. The function qpdf_oh_get_binary_string_value takes a length + * pointer, which can be useful if you are retrieving the value of a string that is expected to + * contain binary data, such as a checksum or document ID. It is always valid to call + * qpdf_get_last_string_length, but it is usually not necessary as C strings returned by the + * library are only expected to be able to contain null characters if their values originate + * from PDF strings in the input. + */ + QPDF_DLL + size_t qpdf_get_last_string_length(qpdf_data qpdf); + + QPDF_DLL + char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + + QPDF_DLL + int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n); + + /* In all dictionary APIs, keys are specified/represented as canonicalized name strings starting + * with / and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle for + * details. + */ + + /* "C"-specific dictionary key iteration */ + + /* Iteration is allowed on only one dictionary at a time. */ + QPDF_DLL + void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh dict); + QPDF_DLL + QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf); + /* The memory returned by qpdf_oh_dict_next_key is owned by qpdf_data. It is good until the next + * call to qpdf_oh_dict_next_key with the same qpdf_data object. Calling the function again, + * even with a different dict, invalidates previous return values. + */ + QPDF_DLL + char const* qpdf_oh_dict_next_key(qpdf_data qpdf); + + /* end "C"-specific dictionary key iteration */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_null(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value); + QPDF_DLL + qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf, double value, int decimal_places); + QPDF_DLL + qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name); + QPDF_DLL + qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str); + QPDF_DLL + qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str); + /* Use qpdf_oh_new_binary_string for creating a string that may contain arbitrary binary data + * including embedded null characters. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_array(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf); + + /* Create a new stream. Use qpdf_oh_get_dict to get (and subsequently modify) the stream + * dictionary if needed. See comments in QPDFObjectHandle.hh for newStream() for additional + * notes. You must call qpdf_oh_replace_stream_data to provide data for the stream. See STREAM + * FUNCTIONS below. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf); + + QPDF_DLL + void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item); + QPDF_DLL + void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at); + + QPDF_DLL + void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + QPDF_DLL + void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + + QPDF_DLL + qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh); + + /* Note about foreign objects: the C API does not have enough information in the value of a + * qpdf_oh to know what QPDF object it belongs to. To uniquely specify a qpdf object handle from + * a specific qpdf_data instance, you always pair the qpdf_oh with the correct qpdf_data. + * Otherwise, you are likely to get completely the wrong object if you are not lucky enough to + * get an error about the object being invalid. + */ + + /* Copy foreign object: the qpdf_oh returned belongs to `qpdf`, while `foreign_oh` belongs to + * `other_qpdf`. + */ + QPDF_DLL + qpdf_oh qpdf_oh_copy_foreign_object(qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh); + + /* STREAM FUNCTIONS */ + + /* These functions provide basic access to streams and stream data. They are not as + * comprehensive as what is in QPDFObjectHandle, but they do allow for working with streams and + * stream data as caller-managed memory. + */ + + /* Get stream data as a buffer. The buffer is allocated with malloc and must be freed by the + * caller. The size of the buffer is stored in *len. The arguments are similar to those in + * QPDFObjectHandle::pipeStreamData. To get raw stream data, pass qpdf_dl_none as decode_level. + * Otherwise, filtering is attempted and *filtered is set to indicate whether it was successful. + * If *filtered is QPDF_FALSE, then raw, unfiltered stream data was returned. You may pass a + * null pointer as filtered if you don't care about the result. If you pass a null pointer as + * bufp (and len), the value of filtered will be set to whether the stream can be filterable. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + enum qpdf_stream_decode_level_e decode_level, + QPDF_BOOL* filtered, + unsigned char** bufp, + size_t* len); + + /* This function returns the concatenation of all of a page's content streams as a single, + * dynamically allocated buffer. As with qpdf_oh_get_stream_data, the buffer is allocated with + * malloc and must be freed by the caller. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_page_content_data( + qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len); + + /* Call free to release a buffer allocated with malloc. This function can be used to free + * buffers that were dynamically allocated by qpdf functions such as qpdf_oh_get_stream_data or + * qpdf_oh_get_page_content_data. The caller is responsible for calling qpdf_oh_free_buffer (or + * calling free directly) to manage memory properly and avoid memory leaks. This function has no + * equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_free_buffer(unsigned char** bufp); + + /* The data pointed to by bufp will be copied by the library. It does not need to remain valid + * after the call returns. + */ + QPDF_DLL + void qpdf_oh_replace_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + unsigned char const* buf, + size_t len, + qpdf_oh filter, + qpdf_oh decode_parms); + + /* PAGE FUNCTIONS */ + + /* The first time a page function is called, qpdf will traverse the /Pages tree. Subsequent + * calls to retrieve the number of pages or a specific page run in constant time as they are + * accessing the pages cache. If you manipulate the page tree outside of these functions, you + * should call qpdf_update_all_pages_cache. See comments for getAllPages() and + * updateAllPagesCache() in QPDF.hh. + */ + + /* For each function, the corresponding method in QPDF.hh is referenced. Please see comments in + * QPDF.hh for details. + */ + + /* calls getAllPages(). On error, returns -1 and sets error for qpdf_get_error. */ + QPDF_DLL + int qpdf_get_num_pages(qpdf_data qpdf); + /* returns uninitialized object if out of range */ + QPDF_DLL + qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index); + + /* updateAllPagesCache() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf); + + /* findPage() -- return zero-based index. If page is not found, return -1 and save the error to + * be retrieved with qpdf_get_error. + */ + QPDF_DLL + int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh); + + /* pushInheritedAttributesToPage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf); + + /* Functions that add pages may add pages from other files. If adding a page from the same file, + newpage_qpdf and qpdf are the same. + */ + + /* addPage() */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_add_page(qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first); + /* addPageAt() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_add_page_at( + qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL before, qpdf_oh refpage); + /* removePage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page); + + /* GLOBAL OPTIONS AND SETTINGS */ + + QPDF_DLL + /** + * @brief Retrieves a 32-bit unsigned integer value associated with a global option or limit. + * + * This function allows querying of specific parameters, identified by the qpdf_param_e enum, + * and retrieves their associated unsigned 32-bit integer values. The result will be stored in + * the variable pointed to by `value`. For details about the available parameters and their + * meanings see `qpdf/global.hh`. + * + * @param param[in] The parameter for which the value is being retrieved. This must be a valid + * value from the qpdf_param_e enumeration. + * @param value[out] A pointer to a uint32_t to store the retrieved value. This must be a valid, + * non-null pointer. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_get_uint32(enum qpdf_param_e param, uint32_t* value); + + QPDF_DLL + /** + * @brief Sets a global option or limit for the qpdf library to a specified value. + * + * This function is used to configure global options or limits for the qpdf library based on the + * provided parameter and value. The behavior depends on the specific `param` provided and its + * valid range of values. For details about the available parameters and their meanings see + * `qpdf/global.hh`. + * + * @param param[in] The parameter to be set. Must be one of the values defined in the + * qpdf_param_e enumeration. + * @param value[in] The value to assign to the specified parameter. Interpretation of this value + * depends on the parameter being set. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_set_uint32(enum qpdf_param_e param, uint32_t value); +#ifdef __cplusplus +} + +// These C++ functions make it easier to write C++ code that interoperates with the C API. +// See examples/extend-c-api. + +# include +# include + +# include + +// Retrieve the real QPDF object attached to this qpdf_data. +QPDF_DLL +std::shared_ptr qpdf_c_get_qpdf(qpdf_data qpdf); + +// Wrap a C++ function that may throw an exception to translate the exception for retrieval using +// the normal QPDF C API methods. +QPDF_DLL +QPDF_ERROR_CODE qpdf_c_wrap(qpdf_data qpdf, std::function fn); +#endif + +#endif /* QPDF_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdfjob-c.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdfjob-c.h new file mode 100644 index 0000000..a00b923 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdfjob-c.h @@ -0,0 +1,156 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFJOB_C_H +#define QPDFJOB_C_H + +/* + * This file defines a basic "C" API for QPDFJob. See also qpdf-c.h, which defines an API that + * exposes more of the library's API. This API is primarily intended to make it simpler for programs + * in languages other than C++ to incorporate functionality that could be run directly from the + * command-line. + */ + +#include +#include +#include +#include +#ifndef QPDF_NO_WCHAR_T +# include +#endif + +/* + * This file provides a minimal wrapper around QPDFJob. See examples/qpdfjob-c.c for an example of + * its use. + */ + +#ifdef __cplusplus +extern "C" { +#endif + /* SHORT INTERFACE -- These functions are single calls that take care of the whole life cycle of + * QPDFJob. They can be used for one-shot operations where no additional configuration is + * needed. See FULL INTERFACE below. */ + + /* This function does the equivalent of running the qpdf command-line with the given arguments + * and returns the exit code that qpdf would use. argv must be a null-terminated array of + * null-terminated UTF8-encoded strings. If calling this from wmain on Windows, use + * qpdfjob_run_from_wide_argv instead. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_argv(char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_run_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_run_from_wide_argv(wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function runs QPDFJob from a job JSON file. See the "QPDF Job" section of the manual for + * details. The JSON string must be UTF8-encoded. It returns the error code that qpdf would + * return with the equivalent command-line invocation. Exit code values are defined in + * Constants.h in the qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_json(char const* json); + + /* FULL INTERFACE -- new in qpdf11. Similar to the qpdf-c.h API, you must call qpdfjob_init to + * get a qpdfjob_handle and, when done, call qpdfjob_cleanup to free resources. Remaining + * methods take qpdfjob_handle as an argument. This interface requires more calls but also + * offers greater flexibility. + */ + typedef struct _qpdfjob_handle* qpdfjob_handle; + QPDF_DLL + qpdfjob_handle qpdfjob_init(); + + QPDF_DLL + void qpdfjob_cleanup(qpdfjob_handle* j); + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdfjob_set_logger(qpdfjob_handle j, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdfjob_get_logger(qpdfjob_handle j); + + /* This function wraps QPDFJob::initializeFromArgv. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_initialize_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_initialize_from_wide_argv(qpdfjob_handle j, wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function wraps QPDFJob::initializeFromJson. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions using this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json); + + /* This function wraps QPDFJob::run. It returns the error code that qpdf would return with the + * equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run(qpdfjob_handle j); + + /* The following two functions allow a job to be run in two stages - creation of a qpdf_data + * object and writing of the qpdf_data object. This allows the qpdf_data object to be modified + * prior to writing it out. See examples/qpdfjob-remove-annotations for a C++ illustration of + * its use. + * + * This function wraps QPDFJob::createQPDF. It runs the first stage of the job. A nullptr is + * returned if the job did not produce any pdf file to be written. + */ + QPDF_DLL + qpdf_data qpdfjob_create_qpdf(qpdfjob_handle j); + + /* This function wraps QPDFJob::writeQPDF. It returns the error code that qpdf would return with + * the equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. NOTE it is the callers responsibility to clean up the resources + * associated with the qpdf_data object by calling qpdf_cleanup after the call to + * qpdfjob_write_qpdf. + */ + QPDF_DLL + int qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf); + + /* Allow specification of a custom progress reporter. The progress reporter is only used if + * progress is otherwise requested (with the --progress option or "progress": "" in the JSON). + */ + QPDF_DLL + void qpdfjob_register_progress_reporter( + qpdfjob_handle j, void (*report_progress)(int percent, void* data), void* data); + +#ifdef __cplusplus +} +#endif + +#endif /* QPDFJOB_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdflogger-c.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdflogger-c.h new file mode 100644 index 0000000..b3d706a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/qpdf/qpdflogger-c.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFLOGGER_H +#define QPDFLOGGER_H + +/* + * This file provides a C API for QPDFLogger. See QPDFLogger.hh for information about the logger and + * examples/qpdfjob-c-save-attachment.c for an example. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /* To operate on a logger, you need a handle to it. call qpdflogger_default_logger to get a + * handle for the default logger. There are functions in qpdf-c.h and qpdfjob-c.h that also take + * or return logger handles. When you're done with the logger handler, call qpdflogger_cleanup. + * This cleans up the handle but leaves the underlying log object intact. (It uses a shared + * pointer and will be cleaned up automatically when it is no longer in use.) That means you can + * create a logger with qpdflogger_create(), pass the logger handle to a function in qpdf-c.h or + * qpdfjob-c.h, and then clean it up, subject to constraints imposed by the other function. + */ + + typedef struct _qpdflogger_handle* qpdflogger_handle; + QPDF_DLL + qpdflogger_handle qpdflogger_default_logger(); + + /* Calling cleanup on the handle returned by qpdflogger_create destroys the handle but not the + * underlying logger. See comments above. + */ + QPDF_DLL + qpdflogger_handle qpdflogger_create(); + + QPDF_DLL + void qpdflogger_cleanup(qpdflogger_handle* l); + + enum qpdf_log_dest_e { + qpdf_log_dest_default = 0, + qpdf_log_dest_stdout = 1, + qpdf_log_dest_stderr = 2, + qpdf_log_dest_discard = 3, + qpdf_log_dest_custom = 4, + }; + + /* Function should return 0 on success. */ + typedef int (*qpdf_log_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + void qpdflogger_set_info( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_warn( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_error( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + + /* A non-zero value for only_if_not_set means that the save pipeline will only be changed if it + * is not already set. + */ + QPDF_DLL + void qpdflogger_set_save( + qpdflogger_handle l, + enum qpdf_log_dest_e dest, + qpdf_log_fn_t fn, + void* udata, + int only_if_not_set); + QPDF_DLL + void qpdflogger_save_to_standard_output(qpdflogger_handle l, int only_if_not_set); + + /* For testing */ + QPDF_DLL + int qpdflogger_equal(qpdflogger_handle l1, qpdflogger_handle l2); + +#ifdef __cplusplus +} +#endif + +#endif // QPDFLOGGER_H diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/turbojpeg.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/turbojpeg.h new file mode 100644 index 0000000..9255aee --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/turbojpeg.h @@ -0,0 +1,2923 @@ +/* + * Copyright (C) 2009-2015, 2017, 2020-2026 D. R. Commander + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TURBOJPEG_H__ +#define __TURBOJPEG_H__ + +#include + +#define TURBOJPEG_VERSION_NUMBER 3002000 + +#if defined(_WIN32) && defined(DLLDEFINE) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +#define DLLCALL + + +/** + * @addtogroup TurboJPEG + * TurboJPEG API. This API provides an interface for generating, decoding, and + * transforming planar YUV and JPEG images in memory. + * + * @anchor YUVnotes + * YUV Image Format Notes + * ---------------------- + * Technically, the JPEG format uses the YCbCr colorspace (which is technically + * not a colorspace but a color transform), but per the convention of the + * digital video community, the TurboJPEG API uses "YUV" to refer to an image + * format consisting of Y, Cb, and Cr image planes. + * + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (1 in the case of 4:4:4, grayscale, 4:4:0, or 4:4:1; 2 in + * the case of 4:2:2, 4:2:0, or 2:4; 4 in the case of 4:1:1 or 4:1:0.) + * Similarly, the luminance plane height is the image height padded to the + * nearest multiple of the vertical subsampling factor (1 in the case of 4:4:4, + * 4:2:2, grayscale, or 4:1:1; 2 in the case of 4:2:0, 4:4:0, or 4:1:0; 4 in + * the case of 4:4:1 or 2:4.) This is irrespective of any additional padding + * that may be specified as an argument to the various YUV functions. The + * chrominance plane width is equal to the luminance plane width divided by the + * horizontal subsampling factor, and the chrominance plane height is equal to + * the luminance plane height divided by the vertical subsampling factor. + * + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a row alignment + * of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, + * and each of the chrominance planes would be 20 x 35 bytes. + * + * @{ + */ + + +/** + * The number of initialization options + */ +#define TJ_NUMINIT 3 + +/** + * Initialization options + */ +enum TJINIT { + /** + * Initialize the TurboJPEG instance for compression. + */ + TJINIT_COMPRESS, + /** + * Initialize the TurboJPEG instance for decompression. + */ + TJINIT_DECOMPRESS, + /** + * Initialize the TurboJPEG instance for lossless transformation (both + * compression and decompression.) + */ + TJINIT_TRANSFORM +}; + + +/** + * The number of chrominance subsampling options + */ +#define TJ_NUMSAMP 9 + +/** + * Chrominance subsampling options + * + * When pixels are converted from RGB to YCbCr (see #TJCS_YCbCr) or from CMYK + * to YCCK (see #TJCS_YCCK) as part of the JPEG compression process, some of + * the Cb and Cr (chrominance) components can be discarded or averaged together + * to produce a smaller image with little perceptible loss of image quality. + * (The human eye is more sensitive to small changes in brightness than to + * small changes in color.) This is called "chrominance subsampling". + */ +enum TJSAMP { + /** + * 4:4:4 chrominance subsampling (no chrominance subsampling) + * + * The JPEG or YUV image will contain one chrominance component for every + * pixel in the source image. + */ + TJSAMP_444, + /** + * 4:2:2 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x1 + * block of pixels in the source image. + */ + TJSAMP_422, + /** + * 4:2:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x2 + * block of pixels in the source image. + */ + TJSAMP_420, + /** + * Grayscale + * + * The JPEG or YUV image will contain no chrominance components. + */ + TJSAMP_GRAY, + /** + * 4:4:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x2 + * block of pixels in the source image. + * + * @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_440, + /** + * 4:1:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x1 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:1:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:1:1 is + * better able to reproduce sharp horizontal features. + * + * @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_411, + /** + * 4:4:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x4 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:4:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:4:1 is + * better able to reproduce sharp vertical features. + * + * @note 4:4:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_441, + /** + * 4:1:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x2 + * block of pixels in the source image. 4:1:0 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 4:1:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_410, + /** + * 2:4 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x4 + * block of pixels in the source image. 2:4 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 2:4 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_24, + /** + * Unknown subsampling + * + * The JPEG image uses an unusual type of chrominance subsampling. Such + * images can be decompressed into packed-pixel images, but they cannot be + * - decompressed into planar YUV images, + * - losslessly transformed if #TJXOPT_CROP is specified and #TJXOPT_GRAY is + * not specified, or + * - partially decompressed using a cropping region. + */ + TJSAMP_UNKNOWN = -1 +}; + +/** + * iMCU width (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUWidth[TJ_NUMSAMP] = { 8, 16, 16, 8, 8, 32, 8, 32, 16 }; + +/** + * iMCU height (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUHeight[TJ_NUMSAMP] = { 8, 8, 16, 8, 16, 8, 32, 16, 32 }; + + +/** + * The number of pixel formats + */ +#define TJ_NUMPF 12 + +/** + * Pixel formats + */ +enum TJPF { + /** + * RGB pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. + */ + TJPF_RGB, + /** + * BGR pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. + */ + TJPF_BGR, + /** + * RGBX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_RGBX, + /** + * BGRX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_BGRX, + /** + * XBGR pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XBGR, + /** + * XRGB pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XRGB, + /** + * Grayscale pixel format + * + * Each 1-sample pixel represents a luminance (brightness) level from 0 to + * the maximum sample value (which is, for instance, 255 for 8-bit samples or + * 4095 for 12-bit samples or 65535 for 16-bit samples.) + */ + TJPF_GRAY, + /** + * RGBA pixel format + * + * This is the same as @ref TJPF_RGBX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_RGBA, + /** + * BGRA pixel format + * + * This is the same as @ref TJPF_BGRX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_BGRA, + /** + * ABGR pixel format + * + * This is the same as @ref TJPF_XBGR, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ABGR, + /** + * ARGB pixel format + * + * This is the same as @ref TJPF_XRGB, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ARGB, + /** + * CMYK pixel format + * + * Unlike RGB, which is an additive color model used primarily for display, + * CMYK (Cyan/Magenta/Yellow/Key) is a subtractive color model used primarily + * for printing. In the CMYK color model, the value of each color component + * typically corresponds to an amount of cyan, magenta, yellow, or black ink + * that is applied to a white background. In order to convert between CMYK + * and RGB, it is necessary to use a color management system (CMS.) A CMS + * will attempt to map colors within the printer's gamut to perceptually + * similar colors in the display's gamut and vice versa, but the mapping is + * typically not 1:1 or reversible, nor can it be defined with a simple + * formula. Thus, such a conversion is out of scope for a codec library. + * However, the TurboJPEG API allows for compressing packed-pixel CMYK images + * into YCCK JPEG images (see #TJCS_YCCK) and decompressing YCCK JPEG images + * into packed-pixel CMYK images. + */ + TJPF_CMYK, + /** + * Unknown pixel format + * + * Currently this is only used by #tj3LoadImage8(), #tj3LoadImage12(), and + * #tj3LoadImage16(). + */ + TJPF_UNKNOWN = -1 +}; + +/** + * Red offset (in samples) for a given pixel format + * + * This specifies the number of samples that the red component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the red + * component is `pixel[tjRedOffset[TJPF_BGRX]]`. The offset is -1 if the pixel + * format does not have a red component. + */ +static const int tjRedOffset[TJ_NUMPF] = { + 0, 2, 0, 2, 3, 1, -1, 0, 2, 3, 1, -1 +}; +/** + * Green offset (in samples) for a given pixel format + * + * This specifies the number of samples that the green component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the green + * component is `pixel[tjGreenOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a green component. + */ +static const int tjGreenOffset[TJ_NUMPF] = { + 1, 1, 1, 1, 2, 2, -1, 1, 1, 2, 2, -1 +}; +/** + * Blue offset (in samples) for a given pixel format + * + * This specifies the number of samples that the blue component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the blue + * component is `pixel[tjBlueOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a blue component. + */ +static const int tjBlueOffset[TJ_NUMPF] = { + 2, 0, 2, 0, 1, 3, -1, 2, 0, 1, 3, -1 +}; +/** + * Alpha offset (in samples) for a given pixel format + * + * This specifies the number of samples that the alpha component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRA is stored in `unsigned char pixel[]`, then the alpha + * component is `pixel[tjAlphaOffset[TJPF_BGRA]]`. The offset is -1 if the + * pixel format does not have an alpha component. + */ +static const int tjAlphaOffset[TJ_NUMPF] = { + -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; +/** + * Pixel size (in samples) for a given pixel format + */ +static const int tjPixelSize[TJ_NUMPF] = { + 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4 +}; + + +/** + * The number of JPEG colorspaces + */ +#define TJ_NUMCS 5 + +/** + * JPEG colorspaces + */ +enum TJCS { + /** + * RGB colorspace + * + * When generating the JPEG image, the R, G, and B components in the source + * image are reordered into image planes, but no colorspace conversion or + * subsampling is performed. RGB JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats, but they cannot be generated from or + * decompressed to planar YUV images. + */ + TJCS_RGB, + /** + * YCbCr colorspace + * + * YCbCr is not an absolute colorspace but rather a mathematical + * transformation of RGB designed solely for storage and transmission. YCbCr + * images must be converted to RGB before they can be displayed. In the + * YCbCr colorspace, the Y (luminance) component represents the black & white + * portion of the original image, and the Cb and Cr (chrominance) components + * represent the color portion of the original image. Historically, the + * analog equivalent of this transformation allowed the same signal to be + * displayed to both black & white and color televisions, but JPEG images + * primarily use YCbCr because it optionally allows the color data to be + * subsampled in order to reduce network and disk usage. YCbCr is the most + * common JPEG colorspace, and YCbCr JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats. YCbCr JPEG images can also be generated from + * and decompressed to planar YUV images. + */ + TJCS_YCbCr, + /** + * Grayscale colorspace + * + * The JPEG image retains only the luminance data (Y component), and any + * color data from the source image is discarded. Grayscale JPEG images can + * be generated from and decompressed to packed-pixel images with any of the + * extended RGB or grayscale pixel formats, or they can be generated from + * and decompressed to planar YUV images. + */ + TJCS_GRAY, + /** + * CMYK colorspace + * + * When generating the JPEG image, the C, M, Y, and K components in the + * source image are reordered into image planes, but no colorspace conversion + * or subsampling is performed. CMYK JPEG images can only be generated from + * and decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_CMYK, + /** + * YCCK colorspace + * + * YCCK (AKA "YCbCrK") is not an absolute colorspace but rather a + * mathematical transformation of CMYK designed solely for storage and + * transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + * reversibly transformed into YCCK, and as with YCbCr, the chrominance + * components in the YCCK pixels can be subsampled without incurring major + * perceptual loss. YCCK JPEG images can only be generated from and + * decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_YCCK, + /** + * Default colorspace + * + * Generate a grayscale JPEG image if #TJPARAM_SUBSAMP is set to + * #TJSAMP_GRAY, a YCCK JPEG image if the source image is CMYK, and a YCbCr + * JPEG image otherwise. + */ + TJCS_DEFAULT = -1 +}; + + +/** + * Parameters + */ +enum TJPARAM { + /** + * Error handling behavior + * + * **Value** + * - `0` *[default]* Allow the current compression/decompression/transform + * operation to complete unless a fatal error is encountered. + * - `1` Immediately discontinue the current + * compression/decompression/transform operation if a warning (non-fatal + * error) occurs. + */ + TJPARAM_STOPONWARNING, + /** + * Row order in packed-pixel source/destination images + * + * **Value** + * - `0` *[default]* top-down (X11) order + * - `1` bottom-up (Windows, OpenGL) order + */ + TJPARAM_BOTTOMUP, + /** + * JPEG destination buffer (re)allocation [compression, lossless + * transformation] + * + * **Value** + * - `0` *[default]* Attempt to allocate or reallocate the JPEG destination + * buffer as needed. + * - `1` Generate an error if the JPEG destination buffer is invalid or too + * small. + */ + TJPARAM_NOREALLOC, + /** + * Perceptual quality of lossy JPEG images [compression only] + * + * **Value** + * - `1`-`100` (`1` = worst quality but best compression, `100` = best + * quality but worst compression) *[no default; must be explicitly + * specified]* + */ + TJPARAM_QUALITY, + /** + * Chrominance subsampling level + * + * The JPEG or YUV image uses (decompression, decoding) or will use (lossy + * compression, encoding) the specified level of chrominance subsampling. + * + * **Value** + * - One of the @ref TJSAMP "chrominance subsampling options" *[no default; + * must be explicitly specified for lossy compression, encoding, and + * decoding]* + */ + TJPARAM_SUBSAMP, + /** + * JPEG width (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGWIDTH, + /** + * JPEG height (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGHEIGHT, + /** + * Data precision (bits per sample) + * + * The JPEG image uses (decompression) or will use (lossless compression) the + * specified number of bits per sample. This parameter also specifies the + * target data precision when loading a PNG or PBMPLUS file with + * #tj3LoadImage8(), #tj3LoadImage12(), or #tj3LoadImage16() and the source + * data precision when saving a PNG or PBMPLUS file with #tj3SaveImage8(), + * #tj3SaveImage12(), or #tj3SaveImage16(). + * + * The data precision is the number of bits in the maximum sample value, + * which may not be the same as the width of the data type used to store the + * sample. + * + * **Value** + * - `8` or `12` for lossy JPEG images; `2` to `16` for lossless JPEG, PNG, + * and PBMPLUS images + * + * 12-bit JPEG data precision implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is set. + */ + TJPARAM_PRECISION, + /** + * JPEG colorspace + * + * The JPEG image uses (decompression) or will use (lossy compression) the + * specified colorspace. + * + * **Value** + * - One of the @ref TJCS "JPEG colorspaces" *[default for lossy compression: + * automatically selected based on the subsampling level and pixel format]* + */ + TJPARAM_COLORSPACE, + /** + * Chrominance upsampling algorithm [lossy decompression only] + * + * **Value** + * - `0` *[default]* Use smooth upsampling when decompressing a JPEG image + * that was generated using 4:2:2, 4:2:0, or 4:4:0 chrominance subsampling. + * This creates a smooth transition between neighboring chrominance + * components in order to reduce upsampling artifacts in the decompressed + * image. + * - `1` Use the fastest chrominance upsampling algorithm available, which + * may combine upsampling with color conversion. + */ + TJPARAM_FASTUPSAMPLE, + /** + * DCT/IDCT algorithm [lossy compression and decompression] + * + * **Value** + * - `0` *[default]* Use the most accurate DCT/IDCT algorithm available. + * - `1` Use the fastest DCT/IDCT algorithm available. + * + * This parameter is provided mainly for backward compatibility with libjpeg, + * which historically implemented several different DCT/IDCT algorithms + * because of performance limitations with 1990s CPUs. In the libjpeg-turbo + * implementation of the TurboJPEG API: + * - The "fast" and "accurate" DCT/IDCT algorithms perform similarly on + * modern x86/x86-64 CPUs that support AVX2 instructions. + * - The "fast" algorithm is generally only about 5-15% faster than the + * "accurate" algorithm on other types of CPUs. + * - The difference in accuracy between the "fast" and "accurate" algorithms + * is the most pronounced at JPEG quality levels above 90 and tends to be + * more pronounced with decompression than with compression. + * - For JPEG quality levels above 97, the "fast" algorithm degrades and is + * not fully accelerated, so it is slower than the "accurate" algorithm. + */ + TJPARAM_FASTDCT, + /** + * Huffman table optimization [lossy compression, lossless transformation] + * + * **Value** + * - `0` *[default]* The JPEG image will use the default Huffman tables. + * - `1` Optimal Huffman tables will be computed for the JPEG image. For + * lossless transformation, this can also be specified using + * #TJXOPT_OPTIMIZE. + * + * Huffman table optimization improves compression slightly (generally 5% or + * less), but it reduces compression performance considerably. + */ + TJPARAM_OPTIMIZE, + /** + * Progressive JPEG + * + * In a progressive JPEG image, the DCT coefficients are split across + * multiple "scans" of increasing quality. Thus, a low-quality scan + * containing the lowest-frequency DCT coefficients can be transmitted first + * and refined with subsequent higher-quality scans containing + * higher-frequency DCT coefficients. When using Huffman entropy coding, the + * progressive JPEG format also provides an "end-of-bands (EOB) run" feature + * that allows large groups of zeroes, potentially spanning multiple MCUs, + * to be represented using only a few bytes. + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image is (decompression) or will be (compression, lossless transformation) + * single-scan. + * - `1` The lossy JPEG image is (decompression) or will be (compression, + * lossless transformation) progressive. For lossless transformation, this + * can also be specified using #TJXOPT_PROGRESSIVE. + * + * Progressive JPEG images generally have better compression ratios than + * single-scan JPEG images (much better if the image has large areas of solid + * color), but progressive JPEG compression and decompression is considerably + * slower than single-scan JPEG compression and decompression. Can be + * combined with #TJPARAM_ARITHMETIC. Implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is also set. + */ + TJPARAM_PROGRESSIVE, + /** + * Progressive JPEG scan limit for lossy JPEG images [decompression, lossless + * transformation] + * + * Setting this parameter causes the decompression and transform functions to + * return an error if the number of scans in a progressive JPEG image exceeds + * the specified limit. The primary purpose of this is to allow + * security-critical applications to guard against an exploit of the + * progressive JPEG format described in + * this report. + * + * **Value** + * - maximum number of progressive JPEG scans that the decompression and + * transform functions will process *[default: `0` (no limit)]* + * + * @see #TJPARAM_PROGRESSIVE + */ + TJPARAM_SCANLIMIT, + /** + * Arithmetic entropy coding + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image uses (decompression) or will use (compression, lossless + * transformation) Huffman entropy coding. + * - `1` The lossy JPEG image uses (decompression) or will use (compression, + * lossless transformation) arithmetic entropy coding. For lossless + * transformation, this can also be specified using #TJXOPT_ARITHMETIC. + * + * Arithmetic entropy coding generally improves compression relative to + * Huffman entropy coding, but it reduces compression and decompression + * performance considerably. Can be combined with #TJPARAM_PROGRESSIVE. + */ + TJPARAM_ARITHMETIC, + /** + * Lossless JPEG + * + * **Value** + * - `0` *[default for compression]* The JPEG image is (decompression) or + * will be (compression) lossy/DCT-based. + * - `1` The JPEG image is (decompression) or will be (compression) + * lossless/predictive. + * + * In most cases, lossless JPEG compression and decompression is considerably + * slower than lossy JPEG compression and decompression, and lossless JPEG + * images are much larger than lossy JPEG images. Thus, lossless JPEG images + * are typically used only for applications that require mathematically + * lossless compression. Also note that the following features are not + * available with lossless JPEG images: + * - Colorspace conversion (lossless JPEG images always use #TJCS_RGB, + * #TJCS_GRAY, or #TJCS_CMYK, depending on the pixel format of the source + * image) + * - Chrominance subsampling (lossless JPEG images always use #TJSAMP_444) + * - JPEG quality selection + * - DCT/IDCT algorithm selection + * - Progressive JPEG + * - Arithmetic entropy coding + * - Compression from/decompression to planar YUV images (this parameter is + * ignored by #tj3CompressFromYUV8() and #tj3CompressFromYUVPlanes8()) + * - Decompression scaling + * - Lossless transformation + * + * @see #TJPARAM_LOSSLESSPSV, #TJPARAM_LOSSLESSPT + */ + TJPARAM_LOSSLESS, + /** + * Lossless JPEG predictor selection value (PSV) + * + * **Value** + * - `1`-`7` *[default for compression: `1`]* + * + * Lossless JPEG compression shares no algorithms with lossy JPEG + * compression. Instead, it uses differential pulse-code modulation (DPCM), + * an algorithm whereby each sample is encoded as the difference between the + * sample's value and a "predictor", which is based on the values of + * neighboring samples. If Ra is the sample immediately to the left of the + * current sample, Rb is the sample immediately above the current sample, and + * Rc is the sample diagonally to the left and above the current sample, then + * the relationship between the predictor selection value and the predictor + * is as follows: + * + * PSV | Predictor + * ----|---------- + * 1 | Ra + * 2 | Rb + * 3 | Rc + * 4 | Ra + Rb – Rc + * 5 | Ra + (Rb – Rc) / 2 + * 6 | Rb + (Ra – Rc) / 2 + * 7 | (Ra + Rb) / 2 + * + * Predictors 1-3 are 1-dimensional predictors, whereas Predictors 4-7 are + * 2-dimensional predictors. The best predictor for a particular image + * depends on the image. + * + * @see #TJPARAM_LOSSLESS + */ + TJPARAM_LOSSLESSPSV, + /** + * Lossless JPEG point transform (Pt) + * + * **Value** + * - `0` through ***precision*** *- 1*, where ***precision*** is the JPEG + * data precision in bits *[default for compression: `0`]* + * + * A point transform value of `0` is necessary in order to generate a fully + * lossless JPEG image. (A non-zero point transform value right-shifts the + * input samples by the specified number of bits, which is effectively a form + * of lossy color quantization.) + * + * @see #TJPARAM_LOSSLESS, #TJPARAM_PRECISION + */ + TJPARAM_LOSSLESSPT, + /** + * JPEG restart marker interval in MCUs [lossy compression, + * lossless transformation] + * + * The nature of entropy coding is such that a corrupt JPEG image cannot + * be decompressed beyond the point of corruption unless it contains restart + * markers. A restart marker stops and restarts the entropy coding algorithm + * so that, if a JPEG image is corrupted, decompression can resume at the + * next marker. Thus, adding more restart markers improves the fault + * tolerance of the JPEG image, but adding too many restart markers can + * adversely affect the compression ratio and performance. + * + * In typical JPEG images, an MCU (Minimum Coded Unit) is the minimum set of + * interleaved "data units" (8x8 DCT blocks if the image is lossy or samples + * if the image is lossless) necessary to represent at least one data unit + * per component. (For example, an MCU in an interleaved lossy JPEG image + * that uses 4:2:2 subsampling consists of two luminance blocks followed by + * one block for each chrominance component.) In single-component or + * non-interleaved JPEG images, an MCU is the same as a data unit. + * + * **Value** + * - the number of MCUs between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTROWS to 0. + */ + TJPARAM_RESTARTBLOCKS, + /** + * JPEG restart marker interval in MCU rows [compression, + * lossless transformation] + * + * See #TJPARAM_RESTARTBLOCKS for a description of restart markers and MCUs. + * An MCU row is a row of MCUs spanning the entire width of the image. + * + * **Value** + * - the number of MCU rows between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTBLOCKS to + * 0. + */ + TJPARAM_RESTARTROWS, + /** + * JPEG horizontal pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified horizontal pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_XDENSITY, + /** + * JPEG vertical pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified vertical pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_YDENSITY, + /** + * JPEG pixel density units + * + * **Value** + * - `0` *[default for compression]* The pixel density of the JPEG image is + * expressed (decompression) or will be expressed (compression) in unknown + * units. + * - `1` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/inch. + * - `2` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/cm. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_XDENSITY, TJPARAM_YDENSITY + */ + TJPARAM_DENSITYUNITS, + /** + * Memory limit for intermediate buffers + * + * **Value** + * - the maximum amount of memory (in megabytes) that will be allocated for + * intermediate buffers, which are used with progressive JPEG compression and + * decompression, Huffman table optimization, lossless JPEG compression, and + * lossless transformation *[default: `0` (no limit)]* + */ + TJPARAM_MAXMEMORY, + /** + * Image size limit [decompression, lossless transformation, packed-pixel + * image loading] + * + * Setting this parameter causes the decompression, transform, and image + * loading functions to return an error if the number of pixels in the source + * image exceeds the specified limit. This allows security-critical + * applications to guard against excessive memory consumption. + * + * **Value** + * - maximum number of pixels that the decompression, transform, and image + * loading functions will process *[default: `0` (no limit)]* + */ + TJPARAM_MAXPIXELS, + /** + * Marker copying behavior [decompression, lossless transformation, + * packed-pixel image I/O] + * + * **Value [lossless transformation]** + * - `0` Do not copy any extra markers (including comments, JFIF thumbnails, + * Exif data, and ICC profile data) from the source image to the destination + * image. + * - `1` Do not copy any extra markers, except comment (COM) markers, from + * the source image to the destination image. + * - `2` *[default]* Copy all extra markers from the source image to the + * destination image. + * - `3` Copy all extra markers, except ICC profile data (APP2 markers), from + * the source image to the destination image. + * - `4` Do not copy any extra markers, except ICC profile data (APP2 + * markers), from the source image to the destination image. + * + * #TJXOPT_COPYNONE overrides this parameter for a particular transform. + * This parameter overrides any ICC profile that was previously associated + * with the TurboJPEG instance using #tj3SetICCProfile(), #tj3LoadImage8(), + * #tj3LoadImage12(), or #tj3LoadImage16(). + * + * If this parameter is set to `2` or `4`: + * - When decompressing, #tj3DecompressHeader() extracts the ICC profile from + * a JPEG image. #tj3GetICCProfile() can then be used to retrieve the + * profile. + * - When loading a PNG image using a TurboJPEG compression instance, + * #tj3LoadImage8(), #tj3LoadImage12(), and #tj3LoadImage16() extract the + * ICC profile from the PNG image and associate the profile with the + * TurboJPEG instance. #tj3GetICCProfile() can then be used to retrieve + * the profile. + * - When saving a PNG image using a TurboJPEG decompression instance, + * #tj3SaveImage8(), #tj3SaveImage12(), and #tj3SaveImage16() transfer the + * ICC profile that was previously extracted from a JPEG image to the PNG + * image. + */ + TJPARAM_SAVEMARKERS +}; + + +/** + * The number of error codes + */ +#define TJ_NUMERR 2 + +/** + * Error codes + */ +enum TJERR { + /** + * The error was non-fatal and recoverable, but the destination image may + * still be corrupt. + */ + TJERR_WARNING, + /** + * The error was fatal and non-recoverable. + */ + TJERR_FATAL +}; + + +/** + * The number of transform operations + */ +#define TJ_NUMXOP 8 + +/** + * Transform operations for #tj3Transform() + */ +enum TJXOP { + /** + * Do not transform the position of the image pixels. + */ + TJXOP_NONE, + /** + * Flip (mirror) image horizontally. This transform is imperfect if there + * are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_HFLIP, + /** + * Flip (mirror) image vertically. This transform is imperfect if there are + * any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_VFLIP, + /** + * Transpose image (flip/mirror along upper left to lower right axis.) This + * transform is always perfect. + */ + TJXOP_TRANSPOSE, + /** + * Transverse transpose image (flip/mirror along upper right to lower left + * axis.) This transform is imperfect if there are any partial iMCUs in the + * image (see #TJXOPT_PERFECT.) + */ + TJXOP_TRANSVERSE, + /** + * Rotate image clockwise by 90 degrees. This transform is imperfect if + * there are any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT90, + /** + * Rotate image 180 degrees. This transform is imperfect if there are any + * partial iMCUs in the image (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT180, + /** + * Rotate image counter-clockwise by 90 degrees. This transform is imperfect + * if there are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT270 +}; + + +/** + * This option causes #tj3Transform() to return an error if the transform is + * not perfect. Lossless transforms operate on iMCUs, the size of which + * depends on the level of chrominance subsampling used (see #tjMCUWidth and + * #tjMCUHeight.) If the image's width or height is not evenly divisible by + * the iMCU size, then there will be partial iMCUs on the right and/or bottom + * edges. It is not possible to move these partial iMCUs to the top or left of + * the image, so any transform that would require that is "imperfect." If this + * option is not specified, then any partial iMCUs that cannot be transformed + * will be left in place, which will create odd-looking strips on the right or + * bottom edge of the image. + */ +#define TJXOPT_PERFECT (1 << 0) +/** + * Discard any partial iMCUs that cannot be transformed. + */ +#define TJXOPT_TRIM (1 << 1) +/** + * Enable lossless cropping. See #tj3Transform() for more information. + */ +#define TJXOPT_CROP (1 << 2) +/** + * Discard the color data in the source image, and generate a grayscale + * destination image. + */ +#define TJXOPT_GRAY (1 << 3) +/** + * Do not generate a destination image. (This can be used in conjunction with + * a custom filter to capture the transformed DCT coefficients without + * transcoding them.) + */ +#define TJXOPT_NOOUTPUT (1 << 4) +/** + * Generate a progressive destination image instead of a single-scan + * destination image. Progressive JPEG images generally have better + * compression ratios than single-scan JPEG images (much better if the image + * has large areas of solid color), but progressive JPEG decompression is + * considerably slower than single-scan JPEG decompression. Can be combined + * with #TJXOPT_ARITHMETIC. Implies #TJXOPT_OPTIMIZE unless #TJXOPT_ARITHMETIC + * is also specified. + */ +#define TJXOPT_PROGRESSIVE (1 << 5) +/** + * Do not copy any extra markers (including Exif and ICC profile data) from the + * source image to the destination image. + */ +#define TJXOPT_COPYNONE (1 << 6) +/** + * Enable arithmetic entropy coding in the destination image. Arithmetic + * entropy coding generally improves compression relative to Huffman entropy + * coding (the default), but it reduces decompression performance considerably. + * Can be combined with #TJXOPT_PROGRESSIVE. + */ +#define TJXOPT_ARITHMETIC (1 << 7) +/** + * Enable Huffman table optimization for the destination image. Huffman table + * optimization improves compression slightly (generally 5% or less.) + */ +#define TJXOPT_OPTIMIZE (1 << 8) + + +/** + * Scaling factor + */ +typedef struct { + /** + * Numerator + */ + int num; + /** + * Denominator + */ + int denom; +} tjscalingfactor; + +/** + * Cropping region + */ +typedef struct { + /** + * The left boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU width (see #tjMCUWidth) of the + * destination image. For decompression, this must be evenly divisible by + * the scaled iMCU width of the source image. + */ + int x; + /** + * The upper boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU height (see #tjMCUHeight) of the + * destination image. + */ + int y; + /** + * The width of the cropping region. Setting this to 0 is the equivalent of + * setting it to the width of the source JPEG image - x. + */ + int w; + /** + * The height of the cropping region. Setting this to 0 is the equivalent of + * setting it to the height of the source JPEG image - y. + */ + int h; +} tjregion; + +/** + * A #tjregion structure that specifies no cropping + */ +static const tjregion TJUNCROPPED = { 0, 0, 0, 0 }; + +/** + * Lossless transform + */ +typedef struct tjtransform { + /** + * Cropping region + */ + tjregion r; + /** + * One of the @ref TJXOP "transform operations" + */ + int op; + /** + * The bitwise OR of one of more of the @ref TJXOPT_ARITHMETIC + * "transform options" + */ + int options; + /** + * Arbitrary data that can be accessed within the body of the callback + * function + */ + void *data; + /** + * A callback function that can be used to modify the DCT coefficients after + * they are losslessly transformed but before they are transcoded to a new + * JPEG image. This allows for custom filters or other transformations to be + * applied in the frequency domain. + * + * @param coeffs pointer to an array of transformed DCT coefficients. (NOTE: + * This pointer is not guaranteed to be valid once the callback returns, so + * applications wishing to hand off the DCT coefficients to another function + * or library should make a copy of them within the body of the callback.) + * + * @param arrayRegion #tjregion structure containing the width and height of + * the array pointed to by `coeffs` as well as its offset relative to the + * component plane. TurboJPEG implementations may choose to split each + * component plane into multiple DCT coefficient arrays and call the callback + * function once for each array. + * + * @param planeRegion #tjregion structure containing the width and height of + * the component plane to which `coeffs` belongs + * + * @param componentID ID number of the component plane to which `coeffs` + * belongs. (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in + * typical JPEG images.) + * + * @param transformID ID number of the transformed image to which `coeffs` + * belongs. This is the same as the index of the transform in the + * `transforms` array that was passed to #tj3Transform(). + * + * @param transform a pointer to a #tjtransform structure that specifies the + * parameters and/or cropping region for this transform + * + * @return 0 if the callback was successful, or -1 if an error occurred. + */ + int (*customFilter) (short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentID, int transformID, + struct tjtransform *transform); +} tjtransform; + +/** + * TurboJPEG instance handle + */ +typedef void *tjhandle; + + +/** + * Compute the scaled value of `dimension` using the given scaling factor. + * This macro performs the integer equivalent of `ceil(dimension * + * scalingFactor)`. + */ +#define TJSCALED(dimension, scalingFactor) \ + (((dimension) * scalingFactor.num + scalingFactor.denom - 1) / \ + scalingFactor.denom) + +/** + * A #tjscalingfactor structure that specifies a scaling factor of 1/1 (no + * scaling) + */ +static const tjscalingfactor TJUNSCALED = { 1, 1 }; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Create a new TurboJPEG instance. + * + * @param initType one of the @ref TJINIT "initialization options" + * + * @return a handle to the newly-created instance, or NULL if an error occurred + * (see #tj3GetErrorStr().) + */ +#ifdef __DOXYGEN__ +DLLEXPORT tjhandle tj3Init(int initType); +#else +#define tj3Init(initType) tj3InitVersion(initType, TURBOJPEG_VERSION_NUMBER) +#endif + +DLLEXPORT tjhandle tj3InitVersion(int initType, int apiVersion); + + +/** + * Destroy a TurboJPEG instance. + * + * @param handle handle to a TurboJPEG instance. If the handle is NULL, then + * this function has no effect. + */ +DLLEXPORT void tj3Destroy(tjhandle handle); + + +/** + * Returns a descriptive error message explaining why the last command failed. + * + * @param handle handle to a TurboJPEG instance, or NULL if the error was + * generated by a global function (but note that retrieving the error message + * for a global function is thread-safe only on platforms that support + * thread-local storage.) + * + * @return a descriptive error message explaining why the last command failed. + */ +DLLEXPORT char *tj3GetErrorStr(tjhandle handle); + + +/** + * Returns a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + * + * @param handle handle to a TurboJPEG instance + * + * @return a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + */ +DLLEXPORT int tj3GetErrorCode(tjhandle handle); + + +/** + * Set the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @param value value of the parameter (refer to @ref TJPARAM + * "parameter documentation") + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3Set(tjhandle handle, int param, int value); + + +/** + * Get the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @return the value of the specified parameter, or -1 if the value is unknown. + */ +DLLEXPORT int tj3Get(tjhandle handle, int param); + + +/** + * Allocate a byte buffer for use with TurboJPEG. You should always use this + * function to allocate the JPEG destination buffer(s) for the compression and + * transform functions unless you are disabling automatic buffer (re)allocation + * (by setting #TJPARAM_NOREALLOC.) + * + * @param bytes the number of bytes to allocate + * + * @return a pointer to a newly-allocated buffer with the specified number of + * bytes. + * + * @see tj3Free() + */ +DLLEXPORT void *tj3Alloc(size_t bytes); + + +/** + * Free a byte buffer previously allocated by TurboJPEG. You should always use + * this function to free JPEG destination buffer(s) that were automatically + * (re)allocated by the compression and transform functions or that were + * manually allocated using #tj3Alloc(). + * + * @param buffer address of the buffer to free. If the address is NULL, then + * this function has no effect. + * + * @see tj3Alloc() + */ +DLLEXPORT void tj3Free(void *buffer); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image with + * the given parameters. The number of bytes returned by this function is + * larger than the size of the uncompressed source image. The reason for this + * is that the JPEG format uses 16-bit coefficients, so it is possible for a + * very high-quality source image with very high-frequency content to expand + * rather than compress when converted to the JPEG format. Such images + * represent very rare corner cases, but since there is no way to predict the + * size of a JPEG image prior to compression, the corner cases have to be + * handled. + * + * @param width width (in pixels) of the image + * + * @param height height (in pixels) of the image + * + * @param jpegSubsamp the level of chrominance subsampling to be used when + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) #TJSAMP_UNKNOWN is treated like + * #TJSAMP_444, since a buffer large enough to hold a JPEG image with no + * subsampling should also be large enough to hold a JPEG image with an + * arbitrary level of subsampling. Note that lossless JPEG images always + * use #TJSAMP_444. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * image, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3JPEGBufSize(int width, int height, int jpegSubsamp); + + +/** + * The size of the buffer (in bytes) required to hold a unified planar YUV + * image with the given parameters. + * + * @param width width (in pixels) of the image + * + * @param align row alignment (in bytes) of the image (must be a power of 2.) + * Setting this parameter to n specifies that each row in each plane of the + * image will be padded to the nearest multiple of n bytes (1 = unpadded.) + * + * @param height height (in pixels) of the image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the image, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVBufSize(int width, int align, int height, int subsamp); + + +/** + * The size of the buffer (in bytes) required to hold a YUV image plane with + * the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: This is the width of + * the whole image, not the plane width. + * + * @param stride bytes per row in the image plane. Setting this to 0 is the + * equivalent of setting it to the plane width. + * + * @param height height (in pixels) of the YUV image. NOTE: This is the height + * of the whole image, not the plane height. + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the YUV image + * plane, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVPlaneSize(int componentID, int width, int stride, + int height, int subsamp); + + +/** + * The plane width of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane width of a YUV image plane with the given parameters, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneWidth(int componentID, int width, int subsamp); + + +/** + * The plane height of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane height of a YUV image plane with the given parameters, or + * 0 if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneHeight(int componentID, int height, int subsamp); + + +/** + * Embed an ICC (International Color Consortium) color management profile in + * JPEG images generated by subsequent compression and lossless transformation + * operations. + * + * @note Lossless transformation operations ignore this ICC profile unless + * #TJXOPT_COPYNONE is specified or #TJPARAM_SAVEMARKERS is set to something + * other than `2` or `4`. Otherwise the ICC profile in the source image takes + * precedence, even if the source image has no ICC profile. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param iccBuf pointer to a byte buffer containing an ICC profile. A copy is + * made of the ICC profile, so this buffer can be freed or reused as soon as + * this function returns. Setting this parameter to NULL or setting `iccSize` + * to 0 removes any ICC profile that was previously associated with the + * TurboJPEG instance. + * + * @param iccSize size of the ICC profile (in bytes.) Setting this parameter + * to 0 or setting `iccBuf` to NULL removes any ICC profile that was previously + * associated with the TurboJPEG instance. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetICCProfile(tjhandle handle, unsigned char *iccBuf, + size_t iccSize); + + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 2 to 8 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 9 to 12 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress12(tjhandle handle, const short *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 13 to 16 bits of + * data precision per sample into a lossless JPEG image with the same data + * precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress16(tjhandle handle, const unsigned short *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Compress a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into + * an 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or + * @ref TJCS_GRAY "grayscale" JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if compressing a grayscale image) that contain a YUV + * source image to be compressed. These planes can be contiguous or + * non-contiguous in memory. The size of each plane should match the value + * returned by #tj3YUVPlaneSize() for the given image width, height, strides, + * and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer to + * @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to create a JPEG image from a subregion of a larger + * planar YUV image. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + int width, const int *strides, + int height, unsigned char **jpegBuf, + size_t *jpegSize); + + +/** + * Compress an 8-bit-per-sample unified planar YUV image into an + * 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or @ref TJCS_GRAY "grayscale" + * JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be compressed. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param align row alignment (in bytes) of the source image (must be a power + * of 2.) Setting this parameter to n indicates that each row in each plane of + * the source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUV8(tjhandle handle, + const unsigned char *srcBuf, int width, + int align, int height, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * color conversion and downsampling (which are accelerated in the + * libjpeg-turbo implementation) but does not execute any of the other steps in + * the JPEG compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if generating a grayscale image) that will receive the + * encoded image. These planes can be contiguous or non-contiguous in memory. + * Use #tj3YUVPlaneSize() to determine the appropriate size for each plane + * based on the image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the plane width (see @ref YUVnotes + * "YUV Image Format Notes".) If `strides` is NULL, then the strides for all + * planes will be set to their respective plane widths. You can adjust the + * strides in order to add an arbitrary amount of row padding to each plane or + * to encode an RGB or grayscale image into a subregion of a larger planar YUV + * image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUVPlanes8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into an + * 8-bit-per-sample unified planar YUV image. This function performs color + * conversion and downsampling (which are accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * image. Use #tj3YUVBufSize() to determine the appropriate size for this + * buffer based on the image width, height, row alignment, and level of + * chrominance subsampling (see #TJPARAM_SUBSAMP.) The Y, U (Cb), and V (Cr) + * image planes will be stored sequentially in the buffer. (Refer to + * @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align); + + +/** + * Retrieve information about a JPEG image without decompressing it, or prime + * the decompressor with quantization and Huffman tables. If a JPEG image is + * passed to this function, then the @ref TJPARAM "parameters" that describe + * the JPEG image will be set when the function returns. If a JPEG image is + * passed to this function and #TJPARAM_SAVEMARKERS is set to `2` or `4`, then + * the ICC profile (if any) will be extracted from the JPEG image. + * (#tj3GetICCProfile() can then be used to retrieve the profile.) + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing a JPEG image or an + * "abbreviated table specification" (AKA "tables-only") datastream. Passing a + * tables-only datastream to this function primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. + * + * @param jpegSize size of the JPEG image or tables-only datastream (in bytes) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressHeader(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize); + + +/** + * Retrieve the ICC (International Color Consortium) color management profile + * (if any) that was previously extracted from a JPEG image or associated with + * a TurboJPEG compression instance. + * + * @note To extract the ICC profile from a JPEG image, call + * #tj3DecompressHeader() with #TJPARAM_SAVEMARKERS set to `2` or `4`. + * + * @note To associate an ICC profile with a TurboJPEG compression instance, + * call #tj3SetICCProfile() or use #tj3LoadImage8(), #tj3LoadImage12(), or + * #tj3LoadImage16() to load a PNG image with #TJPARAM_SAVEMARKERS set to `2` + * or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param iccBuf address of a pointer to a byte buffer. Upon return: + * - If `iccBuf` is not NULL and there is an ICC profile to retrieve, then + * `*iccBuf` will point to a byte buffer containing the ICC profile. This + * buffer should be freed using #tj3Free(). + * - If `iccBuf` is not NULL and there is no ICC profile to retrieve, then + * `*iccBuf` will be NULL. + * - If `iccBuf` is NULL, then only the ICC profile size will be retrieved, and + * the ICC profile can be retrieved later. + * + * @param iccSize address of a size_t variable. Upon return, the variable will + * contain the ICC profile size (or 0 if there is no ICC profile to retrieve.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3GetICCProfile(tjhandle handle, unsigned char **iccBuf, + size_t *iccSize); + + +/** + * Returns a list of fractional scaling factors that the JPEG decompressor + * supports. + * + * @param numScalingFactors pointer to an integer variable that will receive + * the number of elements in the list + * + * @return a pointer to a list of fractional scaling factors, or NULL if an + * error is encountered (see #tj3GetErrorStr().) + */ +DLLEXPORT tjscalingfactor *tj3GetScalingFactors(int *numScalingFactors); + + +/** + * Set the scaling factor for subsequent lossy decompression operations. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param scalingFactor #tjscalingfactor structure that specifies a fractional + * scaling factor that the decompressor supports (see #tj3GetScalingFactors()), + * or #TJUNSCALED for no scaling. Decompression scaling is a function + * of the IDCT algorithm, so scaling factors are generally limited to multiples + * of 1/8. If the entire JPEG image will be decompressed, then the width and + * height of the scaled destination image can be determined by calling + * #TJSCALED() with the JPEG width and height (see #TJPARAM_JPEGWIDTH and + * #TJPARAM_JPEGHEIGHT) and the specified scaling factor. When decompressing + * into a planar YUV image, an intermediate buffer copy will be performed if + * the width or height of the scaled destination image is not an even multiple + * of the iMCU size (see #tjMCUWidth and #tjMCUHeight.) Note that + * decompression scaling is not available (and the specified scaling factor is + * ignored) when decompressing lossless JPEG images (see #TJPARAM_LOSSLESS), + * since the IDCT algorithm is not used with those images. Note also that + * #TJPARAM_FASTDCT is ignored when decompression scaling is enabled. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetScalingFactor(tjhandle handle, + tjscalingfactor scalingFactor); + + +/** + * Set the cropping region for partially decompressing a lossy JPEG image into + * a packed-pixel image + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param croppingRegion #tjregion structure that specifies a subregion of the + * JPEG image to decompress, or #TJUNCROPPED for no cropping. The + * left boundary of the cropping region must be evenly divisible by the scaled + * iMCU width-- #TJSCALED(#tjMCUWidth[subsamp], scalingFactor), where + * `subsamp` is the level of chrominance subsampling in the JPEG image (see + * #TJPARAM_SUBSAMP) and `scalingFactor` is the decompression scaling factor + * (see #tj3SetScalingFactor().) The cropping region should be specified + * relative to the scaled image dimensions. Unless `croppingRegion` is + * #TJUNCROPPED, the JPEG header must be read (see + * #tj3DecompressHeader()) prior to calling this function. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetCroppingRegion(tjhandle handle, tjregion croppingRegion); + + +/** + * Decompress a JPEG image with 2 to 8 bits of data precision per sample into a + * packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * The @ref TJPARAM "parameters" that describe the JPEG image will be set when + * this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel + * decompressed image. This buffer should normally be + * `pitch * destinationHeight` samples in size. However, you can also use this + * parameter to decompress into a specific region of a larger buffer. NOTE: + * If the JPEG image is lossy, then `destinationHeight` is either the scaled + * JPEG height (see #TJSCALED(), #TJPARAM_JPEGHEIGHT, and + * #tj3SetScalingFactor()) or the height of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationHeight` is the JPEG height. + * + * @param pitch samples per row in the destination image. Normally this should + * be set to destinationWidth * #tjPixelSize[pixelFormat], if the + * destination image should be unpadded. (Setting this parameter to 0 is the + * equivalent of setting it to + * destinationWidth * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decompress into a specific region of + * a larger buffer. NOTE: If the JPEG image is lossy, then `destinationWidth` + * is either the scaled JPEG width (see #TJSCALED(), #TJPARAM_JPEGWIDTH, and + * #tj3SetScalingFactor()) or the width of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationWidth` is the JPEG width. + * + * @param pixelFormat pixel format of the destination image (see @ref + * TJPF "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Decompress8(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned char *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a JPEG image with 9 to 12 bits of data precision per sample into + * a packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * + * @note This function can also be used to decompress an 8-bit-per-sample lossy + * JPEG image into a 12-bit-per-sample packed-pixel image. + * + * @note The JPEG format uses 16-bit DCT coefficients and computes those + * coefficients relative to an 8x8 DCT block. Thus, an 8-bit-per-sample JPEG + * image can preserve most of the signal from an underexposed + * higher-data-precision source image, provided that the data precision of the + * source image is retained in the compressor until the forward DCT stage. + * (Modern digital cameras typically do that, but note that libjpeg-turbo does + * not. Our solution for retaining higher data precision in the compressor is + * simply to generate a 12-bit-per-sample JPEG image.) + * + * @note It may be desirable to preserve as much of that signal as possible in + * the decompressor, to facilitate shadow recovery in the decompressed image. + * Thus, calling this function forces the decompressor to use the + * 12-bit-per-sample decompression pipeline even if the JPEG image has 8 bits + * of data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress12(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, short *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a lossless JPEG image with 13 to 16 bits of data precision per + * sample into a packed-pixel RGB, grayscale, or CMYK image with the same + * data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress16(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned short *dstBuf, + int pitch, int pixelFormat); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * JPEG decompression but leaves out the color conversion step, so a planar YUV + * image is generated instead of a packed-pixel image. The + * @ref TJPARAM "parameters" that describe the JPEG image will be set when this + * function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decompressing a grayscale image) that will receive + * the decompressed image. These planes can be contiguous or non-contiguous in + * memory. Use #tj3YUVPlaneSize() to determine the appropriate size for each + * plane based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), + * strides, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer + * to @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the scaled plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective scaled plane widths. + * You can adjust the strides in order to add an arbitrary amount of row + * padding to each plane or to decompress the JPEG image into a subregion of a + * larger planar YUV image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char **dstPlanes, + int *strides); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into an 8-bit-per-sample + * unified planar YUV image. This function performs JPEG decompression but + * leaves out the color conversion step, so a planar YUV image is generated + * instead of a packed-pixel image. The @ref TJPARAM "parameters" that + * describe the JPEG image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * decompressed image. Use #tj3YUVBufSize() to determine the appropriate size + * for this buffer based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes will be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUV8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char *dstBuf, int align); + + +/** + * Decode a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into an + * 8-bit-per-sample packed-pixel RGB or grayscale image. This function + * performs color conversion (which is accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decoding a grayscale image) that contain a YUV image + * to be decoded. These planes can be contiguous or non-contiguous in memory. + * The size of each plane should match the value returned by #tj3YUVPlaneSize() + * for the given image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to decode a subregion of a larger planar YUV image. + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + const int *strides, unsigned char *dstBuf, + int width, int pitch, int height, + int pixelFormat); + + +/** + * Decode an 8-bit-per-sample unified planar YUV image into an 8-bit-per-sample + * packed-pixel RGB or grayscale image. This function performs color + * conversion (which is accelerated in the libjpeg-turbo implementation) but + * does not execute any of the other steps in the JPEG decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be decoded. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * source buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV source image (must be a + * power of 2.) Setting this parameter to n indicates that each row in each + * plane of the YUV source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int align, unsigned char *dstBuf, int width, + int pitch, int height, int pixelFormat); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image + * transformed with the given transform parameters and/or cropping region. + * This function is a wrapper for #tj3JPEGBufSize() that takes into account + * cropping, transposition of the width and height (which affects the + * destination image dimensions and level of chrominance subsampling), + * grayscale conversion, and the ICC profile (if any) that was previously + * associated with the TurboJPEG instance or extracted from the source image + * (see #tj3SetICCProfile(), #tj3GetICCProfile(), and #TJPARAM_SAVEMARKERS.) + * The JPEG header must be read (see #tj3DecompressHeader()) prior to calling + * this function. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param transform pointer to a #tjtransform structure that specifies the + * transform parameters and/or cropping region for the JPEG image. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * transformed image, or 0 if an error occurred (see #tj3GetErrorStr() and + * #tj3GetErrorCode().) + */ +DLLEXPORT size_t tj3TransformBufSize(tjhandle handle, + const tjtransform *transform); + + +/** + * Losslessly transform a JPEG image into another JPEG image. Lossless + * transforms work by moving the raw DCT coefficients from one JPEG image + * structure to another without altering the values of the coefficients. While + * this is typically faster than decompressing the image, transforming it, and + * re-compressing it, lossless transforms are not free. Each lossless + * transform requires reading and performing entropy decoding on all of the + * coefficients in the source image, regardless of the size of the destination + * image. Thus, this function provides a means of generating multiple + * transformed images from the same source or applying multiple transformations + * simultaneously, in order to eliminate the need to read the source + * coefficients multiple times. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param jpegBuf pointer to a byte buffer containing the JPEG source image to + * transform + * + * @param jpegSize size of the JPEG source image (in bytes) + * + * @param n the number of transformed JPEG images to generate + * + * @param dstBufs pointer to an array of n byte buffers. `dstBufs[i]` will + * receive a JPEG image that has been transformed using the parameters in + * `transforms[i]`. TurboJPEG has the ability to reallocate the JPEG + * destination buffer to accommodate the size of the transformed JPEG image. + * Thus, you can choose to: + * -# pre-allocate the JPEG destination buffer with an arbitrary size using + * #tj3Alloc() and let TurboJPEG grow the buffer as needed, + * -# set `dstBufs[i]` to NULL to tell TurboJPEG to allocate the buffer for + * you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3TransformBufSize(). Under normal circumstances, this should ensure that + * the buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC + * guarantees that it won't be. However, if the source image has a large + * amount of embedded Exif data, then the transformed JPEG image may be larger + * than the worst-case size. #TJPARAM_NOREALLOC cannot be used in that case + * unless the embedded data is discarded using #TJXOPT_COPYNONE or + * #TJPARAM_SAVEMARKERS.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `dstBufs[i]` + * upon return from this function, as it may have changed. + * + * @param dstSizes pointer to an array of n size_t variables that will receive + * the actual sizes (in bytes) of each transformed JPEG image. If `dstBufs[i]` + * points to a pre-allocated buffer, then `dstSizes[i]` should be set to the + * size of the buffer. Otherwise, `dstSizes[i]` is ignored. Upon return, + * `dstSizes[i]` will contain the size of the transformed JPEG image (in + * bytes.) + * + * @param transforms pointer to an array of n #tjtransform structures, each of + * which specifies the transform parameters and/or cropping region for the + * corresponding transformed JPEG image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Transform(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, int n, unsigned char **dstBufs, + size_t *dstSizes, const tjtransform *transforms); + + +/** + * Load a packed-pixel image with 2 to 8 bits of data precision per sample from + * disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG, + * PBMPLUS (PPM/PGM), or Windows BMP format. Windows BMP files require + * 8-bit-per-sample data precision. When loading a PNG or PBMPLUS file, the + * target data precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. If the data precision of the PNG or PBMPLUS file does not match + * the target data precision, then upconverting or downconverting will be + * performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function varies depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files and 8-bit-per-pixel BMP files with a + * grayscale colormap can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned char *tj3LoadImage8(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 9 to 12 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 9 to 12 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 12 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT short *tj3LoadImage12(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 13 to 16 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 13 to 16 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 16 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned short *tj3LoadImage16(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + + +/** + * Save a packed-pixel image with 2 to 8 bits of data precision per sample from + * memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image. The + * image will be stored in PNG, PBMPLUS (PPM/PGM), or Windows BMP format, + * depending on the file extension. Windows BMP files require 8-bit-per-sample + * data precision. When saving a PNG or PBMPLUS file, the source data + * precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in grayscale PNG, PGM, or 8-bit-per-pixel (indexed + * color) BMP format. Otherwise, the image will be stored in truecolor PNG, + * PPM, or 24-bit-per-pixel BMP format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage8(tjhandle handle, const char *filename, + const unsigned char *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 9 to 12 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage12(tjhandle handle, const char *filename, + const short *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 13 to 16 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage16(tjhandle handle, const char *filename, + const unsigned short *buffer, int width, + int pitch, int height, int pixelFormat); + + +/* Backward compatibility functions and macros (nothing to see here) */ + +/* TurboJPEG 1.0+ */ + +#define NUMSUBOPT TJ_NUMSAMP +#define TJ_444 TJSAMP_444 +#define TJ_422 TJSAMP_422 +#define TJ_420 TJSAMP_420 +#define TJ_411 TJSAMP_420 +#define TJ_GRAYSCALE TJSAMP_GRAY + +#define TJ_BGR 1 +#define TJ_BOTTOMUP TJFLAG_BOTTOMUP +#define TJ_FORCEMMX TJFLAG_FORCEMMX +#define TJ_FORCESSE TJFLAG_FORCESSE +#define TJ_FORCESSE2 TJFLAG_FORCESSE2 +#define TJ_ALPHAFIRST 64 +#define TJ_FORCESSE3 TJFLAG_FORCESSE3 +#define TJ_FASTUPSAMPLE TJFLAG_FASTUPSAMPLE + +#define TJPAD(width) (((width) + 3) & (~3)) + +DLLEXPORT unsigned long TJBUFSIZE(int width, int height); + +DLLEXPORT int tjCompress(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, unsigned long *compressedSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelSize, + int flags); + +DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height); + +DLLEXPORT int tjDestroy(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr(void); + +DLLEXPORT tjhandle tjInitCompress(void); + +DLLEXPORT tjhandle tjInitDecompress(void); + +/* TurboJPEG 1.1+ */ + +#define TJ_YUV 512 + +DLLEXPORT unsigned long TJBUFSIZEYUV(int width, int height, int jpegSubsamp); + +DLLEXPORT int tjDecompressHeader2(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp); + +DLLEXPORT int tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int flags); + +DLLEXPORT int tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, int subsamp, int flags); + +/* TurboJPEG 1.2+ */ + +#define TJFLAG_BOTTOMUP 2 +#define TJFLAG_FORCEMMX 8 +#define TJFLAG_FORCESSE 16 +#define TJFLAG_FORCESSE2 32 +#define TJFLAG_FORCESSE3 128 +#define TJFLAG_FASTUPSAMPLE 256 +#define TJFLAG_NOREALLOC 1024 + +DLLEXPORT unsigned char *tjAlloc(int bytes); + +DLLEXPORT unsigned long tjBufSize(int width, int height, int jpegSubsamp); + +DLLEXPORT unsigned long tjBufSizeYUV(int width, int height, int subsamp); + +DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int subsamp, int flags); + +DLLEXPORT void tjFree(unsigned char *buffer); + +DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors); + +DLLEXPORT tjhandle tjInitTransform(void); + +DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, int n, + unsigned char **dstBufs, unsigned long *dstSizes, + tjtransform *transforms, int flags); + +/* TurboJPEG 1.2.1+ */ + +#define TJFLAG_FASTDCT 2048 +#define TJFLAG_ACCURATEDCT 4096 + +/* TurboJPEG 1.4+ */ + +DLLEXPORT unsigned long tjBufSizeYUV2(int width, int align, int height, + int subsamp); + +DLLEXPORT int tjCompressFromYUV(tjhandle handle, const unsigned char *srcBuf, + int width, int align, int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + int width, const int *strides, + int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, + int align, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjDecodeYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + const int *strides, int subsamp, + unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags); + +DLLEXPORT int tjDecompressHeader3(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp, + int *jpegColorspace); + +DLLEXPORT int tjDecompressToYUV2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int align, int height, int flags); + +DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, + unsigned char **dstPlanes, int width, + int *strides, int height, int flags); + +DLLEXPORT int tjEncodeYUV3(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align, int subsamp, + int flags); + +DLLEXPORT int tjEncodeYUVPlanes(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags); + +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); + +DLLEXPORT unsigned long tjPlaneSizeYUV(int componentID, int width, int stride, + int height, int subsamp); + +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp); + +/* TurboJPEG 2.0+ */ + +#define TJFLAG_STOPONWARNING 8192 +#define TJFLAG_PROGRESSIVE 16384 + +DLLEXPORT int tjGetErrorCode(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr2(tjhandle handle); + +DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, + int align, int *height, int *pixelFormat, + int flags); + +DLLEXPORT int tjSaveImage(const char *filename, unsigned char *buffer, + int width, int pitch, int height, int pixelFormat, + int flags); + +/* TurboJPEG 2.1+ */ + +#define TJFLAG_LIMITSCANS 32768 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zconf.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zconf.h new file mode 100644 index 0000000..1ff5e8c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zconf.h @@ -0,0 +1,555 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* #undef Z_PREFIX */ +#define HAVE_STDARG_H 1 +#define HAVE_UNISTD_H 1 + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compress_z z_compress_z +# define compress2_z z_compress2_z +# define compressBound z_compressBound +# define compressBound_z z_compressBound_z +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateBound_z z_deflateBound_z +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflateUsed z_deflateUsed +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define inflate_fixed z_inflate_fixed +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# define uncompress_z z_uncompress_z +# define uncompress2_z z_uncompress2_z +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#ifndef z_const +# ifdef ZLIB_CONST +# define z_const const +# else +# define z_const +# endif +#endif + +#ifdef Z_SOLO +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if HAVE_UNISTD_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if HAVE_STDARG_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# if defined(__WATCOMC__) || defined(__GO32__) || \ + (defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#elif defined(__MINGW32__) +# define z_off64_t long long +#elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +#elif defined(__GO32__) +# define z_off64_t offset_t +#else +# define z_off64_t z_off_t +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zlib.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zlib.h new file mode 100644 index 0000000..a57d336 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zlib.h @@ -0,0 +1,2057 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.3.2, February 17th, 2026 + + Copyright (C) 1995-2026 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 at https://datatracker.ietf.org/doc/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#ifdef ZLIB_BUILD +# include +#else +# include "zconf.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.3.2" +#define ZLIB_VERNUM 0x1320 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 2 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion(void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the input taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_RLE to limit match distances to one (run-length + encoding), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string + matching). Filtered data consists mostly of small values with a somewhat + random distribution, as produced by the PNG filters. In this case, the + compression algorithm is tuned to compress them better. The effect of + Z_FILTERED is to force more Huffman coding and less string matching than the + default; it is intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. + Z_RLE is almost as fast as Z_HUFFMAN_ONLY, but should give better + compression for PNG image data than Huffman only. The degree of string + matching from most to none is: Z_DEFAULT_STRATEGY, Z_FILTERED, Z_RLE, then + Z_HUFFMAN_ONLY. The strategy parameter affects the compression ratio but + never the correctness of the compressed output, even if it is not set + optimally for the given data. Z_FIXED uses the default string matching, but + prevents the use of dynamic Huffman codes, allowing for a simpler decoder + for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); +ZEXTERN z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. + + delfateBound_z() is the same, but takes and returns a size_t length. Note + that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. If an int is 16 bits and memLevel is 9, then + it is possible for the number of pending bytes to not fit in an unsigned. In + that case Z_BUF_ERROR is returned and *pending is set to the maximum value + of an unsigned. + */ + +ZEXTERN int ZEXPORT deflateUsed(z_streamp strm, + int *bits); +/* + deflateUsed() returns in *bits the most recent number of deflate bits used + in the last byte when flushing to a byte boundary. The result is in 1..8, or + 0 if there has not yet been a flush. This helps determine the location of + the last bit of a deflate stream. + + deflateUsed returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); +/* + This function inserts bits in the inflate input stream. The intent is to + use inflatePrime() to start inflating at a bit position in the middle of a + byte. The provided bits will be used before any bytes are used from + next_in. This function should be used with raw inflate, before the first + inflate() call, after inflateInit2() or inflateReset(). It can also be used + after an inflate() return indicates the end of a deflate block or header + when using Z_BLOCK. bits must be less than or equal to 16, and that many of + the least significant bits of value will be inserted in the input. The + other bits in value can be non-zero, and will be ignored. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent, or if bits is out of range. If inflate was + in the middle of processing a header, trailer, or stored block lengths, then + it is possible for there to be only eight bits available in the bit buffer. + In that case, bits > 8 is considered out of range. However, when used as + outlined above, there will always be 16 bits available in the buffer for + insertion. As noted in its documentation above, inflate records the number + of bits in the bit buffer on return in data_type. 32 minus that is the + number of bits available for insertion. inflatePrime does not update + data_type with the new number of bits in buffer. +*/ + +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) The extra, name, and comment pointers + much each be either Z_NULL or point to space to store that information from + the header. If extra is not Z_NULL, then extra_max contains the maximum + number of bytes that can be written to extra. Once done is true, extra_len + contains the actual extra field length, and extra contains the extra field, + or that field truncated if extra_max is less than extra_len. If name is not + Z_NULL, then up to name_max characters, including the terminating zero, are + written there. If comment is not Z_NULL, then up to comm_max characters, + including the terminating zero, are written there. The application can tell + that the name or comment did not fit in the provided space by the absence of + a terminating zero. If any of extra, name, or comment are not present in + the header, then that field's pointer is set to Z_NULL. This allows the use + of deflateSetHeader() with the returned structure to duplicate the header. + Note that if those fields initially pointed to allocated memory, then the + application will need to save them elsewhere so that they can be eventually + freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); + +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (all zeros is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() is not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + 27: 0 = gzprintf() present, 1 = not -- 1 means gzprintf() returns an error + + Remainder: + 28-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. The _z versions of the functions use the size_t + type for lengths. Note that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT compress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); +ZEXTERN int ZEXPORT compress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen, + int level); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); +ZEXTERN z_size_t ZEXPORT compressBound_z(z_size_t sourceLen); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT uncompress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. On entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) On exit, *destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); +ZEXTERN int ZEXPORT uncompress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. 'T' cannot be + used to force transparent reading. Transparent reading is automatically + performed if there is no gzip header at the start. Transparent reading can + be disabled with the 'G' option, which will instead return an error if there + is no gzip header. 'N' will open the file in non-blocking mode. + + 'a' can be used instead of 'w' to request that the gzip stream that will + be written be appended to the file. '+' will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + 'x' when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of 'e' when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. Note that if 'N' is in mode for non-blocking, the + open() itself can fail in order to not block. In that case gzopen() will + return NULL and errno will be EAGAIN or ENONBLOCK. The call to gzopen() can + then be re-tried. If the application would like to block on opening the + file, then it can use open() without O_NONBLOCK, and then gzdopen() with the + resulting file descriptor and 'N' in the mode, which will set it to non- + blocking. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. An + 'e' in mode will set fd's flag to close the file on an execve() call. An 'N' + in mode will set fd's non-blocking flag. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzread() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. If some data was read before an error, then that data is + returned until exhausted, after which the next call will signal the error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as that of fread() implementations in common libraries. This + could result in data loss if used with size != 1 when reading a concurrently + written file or a non-blocking file. In that case, use size == 1 or gzread() + instead. +*/ + +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written, or 0 in case of error or + if len is 0. If the write destination is non-blocking, then gzwrite() may + return a number of bytes written that is not 0 and less than len. + + If len does not fit in an int, then 0 is returned and nothing is written. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. + + If writing a concurrently read file or a non-blocking file with size != 1, + a partial item could be written, with no way of knowing how much of it was + not written, resulting in data loss. In that case, use size == 1 or + gzwrite() instead. +*/ + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); +#else +ZEXTERN int ZEXPORTVA gzprintf(); +#endif +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. + + In that last case, there may also be a buffer overflow with unpredictable + consequences, which is possible only if zlib was compiled with the insecure + functions sprintf() or vsprintf(), because the secure snprintf() and + vsnprintf() functions were not available. That would only be the case for + a non-ANSI C compiler. zlib may have been built without gzprintf() because + secure functions were not available and having gzprintf() be insecure was + not an option, in which case, gzprintf() returns Z_STREAM_ERROR. All of + these possibilities can be determined using zlibCompileFlags(). + + If a Z_BUF_ERROR is returned, then nothing was written due to a stall on + the non-blocking write destination. +*/ + +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. + The number of characters written may be less than the length of the string + if the write destination is non-blocking. + + If the length of the string does not fit in an int, then -1 is returned + and nothing is written. +*/ + +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If some data was read before an error, + then that data is returned until exhausted, after which the next call will + return NULL to signal the error. + + gzgets can be used on a file being concurrently written, and on a non- + blocking device, both as for gzread(). However lines may be broken in the + middle, leaving it up to the application to reassemble them as needed. +*/ + +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc(gzFile file); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 in + case of end of file or error. If some data was read before an error, then + that data is returned until exhausted, after which the next call will return + -1 to signal the error. + + This is implemented as a macro for speed. As such, it does not do all of + the checking the other functions do. I.e. it does not check to see if file + is NULL, nor whether the structure file points to has been clobbered or not. + + gzgetc can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzgetc() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. +*/ + +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). + + gzungetc(-1, file) will force any pending seek to execute. Then gztell() + will report the position, even if the requested seek reached end of file. + This can be used to determine the number of uncompressed bytes in a gzip + file without having to read it into a buffer. +*/ + +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. For reading or writing, any actual seeking is deferred + until the next read or write operation, or close operation when writing. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind(gzFile file); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof(gzFile file); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect(gzFile file); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). If the input is being written concurrently or the device is non- + blocking, then gzdirect() may give a different answer once four bytes of + input have been accumulated, which is what is needed to confirm or deny a + gzip header. Before this, gzdirect() will return true (1). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose(gzFile file); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); +/* + Return the error message for the last error which occurred on file. + If errnum is not NULL, *errnum is set to zlib error number. If an error + occurred in the file system and not in the compression library, *errnum is + set to Z_ERRNO and the application may consult errno to get the exact error + code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr(gzFile file); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); +/* + Same as adler32(), but with a size_t length. Note that a long is 32 bits + on Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); +/* + Same as crc32(), but with a size_t length. Note that a long is 32 bits on + Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. len2 must be non-negative, otherwise zero is returned. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). len2 must be non-negative, otherwise zero is returned. +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zopfli.h b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zopfli.h new file mode 100644 index 0000000..c079662 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/include/zopfli.h @@ -0,0 +1,94 @@ +/* +Copyright 2011 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: lode.vandevenne@gmail.com (Lode Vandevenne) +Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala) +*/ + +#ifndef ZOPFLI_ZOPFLI_H_ +#define ZOPFLI_ZOPFLI_H_ + +#include +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Options used throughout the program. +*/ +typedef struct ZopfliOptions { + /* Whether to print output */ + int verbose; + + /* Whether to print more detailed output */ + int verbose_more; + + /* + Maximum amount of times to rerun forward and backward pass to optimize LZ77 + compression cost. Good values: 10, 15 for small files, 5 for files over + several MB in size or it will be too slow. + */ + int numiterations; + + /* + If true, splits the data in multiple deflate blocks with optimal choice + for the block boundaries. Block splitting gives better compression. Default: + true (1). + */ + int blocksplitting; + + /* + No longer used, left for compatibility. + */ + int blocksplittinglast; + + /* + Maximum amount of blocks to split into (0 for unlimited, but this can give + extreme results that hurt compression on some files). Default value: 15. + */ + int blocksplittingmax; +} ZopfliOptions; + +/* Initializes options with default values. */ +void ZopfliInitOptions(ZopfliOptions* options); + +/* Output format */ +typedef enum { + ZOPFLI_FORMAT_GZIP, + ZOPFLI_FORMAT_ZLIB, + ZOPFLI_FORMAT_DEFLATE +} ZopfliFormat; + +/* +Compresses according to the given output format and appends the result to the +output. + +options: global program options +output_type: the output format to use +out: pointer to the dynamic output array to which the result is appended. Must + be freed after use +outsize: pointer to the dynamic output array size +*/ +void ZopfliCompress(const ZopfliOptions* options, ZopfliFormat output_type, + const unsigned char* in, size_t insize, + unsigned char** out, size_t* outsize); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ZOPFLI_ZOPFLI_H_ */ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libjpeg.a b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libjpeg.a new file mode 100644 index 0000000..61bc9bd Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libjpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libqpdf.a b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libqpdf.a new file mode 100644 index 0000000..d55384d Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libqpdf.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libturbojpeg.a b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libturbojpeg.a new file mode 100644 index 0000000..969d9b1 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libturbojpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libz.a b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libz.a new file mode 100644 index 0000000..1e7221c Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libz.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libz.so b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libz.so new file mode 100644 index 0000000..e40e870 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libz.so differ diff --git a/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libzopfli.a b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libzopfli.a new file mode 100644 index 0000000..a59107c Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/arm64-v8a/lib/libzopfli.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jconfig.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jconfig.h new file mode 100644 index 0000000..17f95c8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jconfig.h @@ -0,0 +1,60 @@ +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ +#define JPEG_LIB_VERSION 80 + +/* libjpeg-turbo version */ +#define LIBJPEG_TURBO_VERSION 3.1.90 + +/* libjpeg-turbo version in integer form */ +#define LIBJPEG_TURBO_VERSION_NUMBER 3001090 + +/* Support arithmetic encoding when using 8-bit samples */ +#define C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding when using 8-bit samples */ +#define D_ARITH_CODING_SUPPORTED 1 + +/* Support in-memory source/destination managers */ +#define MEM_SRCDST_SUPPORTED 1 + +/* Use accelerated SIMD routines when using 8-bit samples */ +/* #undef WITH_SIMD */ + +/* This version of libjpeg-turbo supports run-time selection of data precision, + * so BITS_IN_JSAMPLE is no longer used to specify the data precision at build + * time. However, some downstream software expects the macro to be defined. + * Since 12-bit data precision is an opt-in feature that requires explicitly + * calling 12-bit-specific libjpeg API functions and using 12-bit-specific data + * types, the unmodified portion of the libjpeg API still behaves as if it were + * built for 8-bit precision, and JSAMPLE is still literally an 8-bit data + * type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here. + */ +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif + +#ifdef _WIN32 + +#undef RIGHT_SHIFT_IS_UNSIGNED + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + +/* Define "INT32" as int, not long, per Windows custom */ +#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ +typedef short INT16; +typedef signed int INT32; +#endif +#define XMD_H /* prevent jmorecfg.h from redefining it */ + +#else + +/* Define if your (broken) compiler shifts signed values as if they were + unsigned. */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jerror.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jerror.h new file mode 100644 index 0000000..892edc3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jerror.h @@ -0,0 +1,336 @@ +/* + * jerror.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2014, 2017, 2021-2023, 2026, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code, string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code, string) code, + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented") +#endif +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#endif +JMESSAGE(JERR_BAD_DCT_COEF, + "DCT coefficient (lossy) or spatial difference (lossless) out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive/lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Requested features are incompatible") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Memory limit exceeded") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED) +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +#endif +JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_RESTART, + "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT3(cinfo, code, p1, p2, p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXITS(cinfo, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX - 1), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo, lvl, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS1(cinfo, lvl, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS2(cinfo, lvl, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMSS(cinfo, lvl, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jmorecfg.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jmorecfg.h new file mode 100644 index 0000000..a4df71c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jmorecfg.h @@ -0,0 +1,389 @@ +/* + * jmorecfg.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, 2026, + * D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255. + * However, darn few applications need more than 4 channels (maybe 5 for CMYK + + * alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +/* JSAMPLE should be the smallest type that will hold the values 0..255. */ + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int)(value)) + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + + +/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */ + +typedef short J12SAMPLE; + +#define MAXJ12SAMPLE 4095 +#define CENTERJ12SAMPLE 2048 + + +/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */ + +typedef unsigned short J16SAMPLE; + +#define MAXJ16SAMPLE 65535 +#define CENTERJ16SAMPLE 32768 + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +typedef unsigned char UINT8; + +/* UINT16 must hold at least the values 0..65535. */ + +typedef unsigned short UINT16; + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. + * + * NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were + * sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to + * long. It also wasn't common (or at least as common) in 1994 for INT32 to be + * defined by platform headers. Since then, however, INT32 is defined in + * several other common places: + * + * Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on + * 32-bit platforms (i.e always a 32-bit signed type.) + * + * basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type + * on modern platforms.) + * + * qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on + * modern platforms.) + * + * This is a recipe for conflict, since "long" and "int" aren't always + * compatible types. Since the definition of INT32 has technically been part + * of the libjpeg API for more than 20 years, we can't remove it, but we do not + * use it internally any longer. We instead define a separate type (JLONG) + * for internal use, which ensures that internal behavior will always be the + * same regardless of any external headers that may be included. + */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. (Note that changing this datatype will + * potentially require modifying the SIMD code. The x86-64 SIMD extensions, + * in particular, assume a 32-bit JDIMENSION.) + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JMETHOD(type, methodname, arglist) type (*methodname) arglist + + +/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS), + * but again, some software relies on this macro. + */ + +#undef FAR +#define FAR + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* accurate integer method */ +#define DCT_IFAST_SUPPORTED /* less accurate int method [legacy feature] */ +#define DCT_FLOAT_SUPPORTED /* floating-point method [legacy feature] */ + +/* Encoder capability options: */ + +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + C_MULTISCAN_FILES_SUPPORTED and + ENTROPY_OPT_SUPPORTED) */ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for lossless JPEG: the default tables don't + * work for lossless mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires + DCT_ISLOW_SUPPORTED) */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial + * feature of libjpeg. The idea was that, if an application developer needed + * to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could + * change these macros, rebuild libjpeg, and link their application statically + * with it. In reality, few people ever did this, because there were some + * severe restrictions involved (cjpeg and djpeg no longer worked properly, + * compressing/decompressing RGB JPEGs no longer worked properly, and the color + * quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since + * all of the O/S-supplied versions of libjpeg were built with the default + * values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications + * have come to regard these values as immutable. + * + * The libjpeg-turbo colorspace extensions provide a much cleaner way of + * compressing from/decompressing to buffers with arbitrary component orders + * and pixel sizes. Thus, we do not support changing the values of RGB_RED, + * RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions + * listed above, changing these values will also break the SIMD extensions and + * the regression tests. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + +#define JPEG_NUMCS 17 + +#define EXT_RGB_RED 0 +#define EXT_RGB_GREEN 1 +#define EXT_RGB_BLUE 2 +#define EXT_RGB_PIXELSIZE 3 + +#define EXT_RGBX_RED 0 +#define EXT_RGBX_GREEN 1 +#define EXT_RGBX_BLUE 2 +#define EXT_RGBX_PIXELSIZE 4 + +#define EXT_BGR_RED 2 +#define EXT_BGR_GREEN 1 +#define EXT_BGR_BLUE 0 +#define EXT_BGR_PIXELSIZE 3 + +#define EXT_BGRX_RED 2 +#define EXT_BGRX_GREEN 1 +#define EXT_BGRX_BLUE 0 +#define EXT_BGRX_PIXELSIZE 4 + +#define EXT_XBGR_RED 3 +#define EXT_XBGR_GREEN 2 +#define EXT_XBGR_BLUE 1 +#define EXT_XBGR_PIXELSIZE 4 + +#define EXT_XRGB_RED 1 +#define EXT_XRGB_GREEN 2 +#define EXT_XRGB_BLUE 3 +#define EXT_XRGB_PIXELSIZE 4 + +static const int rgb_red[JPEG_NUMCS] = { + -1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED, + EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + -1 +}; + +static const int rgb_green[JPEG_NUMCS] = { + -1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN, + EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + -1 +}; + +static const int rgb_blue[JPEG_NUMCS] = { + -1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE, + EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + -1 +}; + +static const int rgb_pixelsize[JPEG_NUMCS] = { + -1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE, + EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + -1 +}; + +/* Definitions for speed-related optimizations. */ + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#ifndef WITH_SIMD +#define MULTIPLIER int /* type for fastest integer multiply */ +#else +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +#endif +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + */ + +#ifndef FAST_FLOAT +#define FAST_FLOAT float +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jpeglib.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jpeglib.h new file mode 100644 index 0000000..f7076a1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/jpeglib.h @@ -0,0 +1,1223 @@ +/* + * jpeglib.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022-2024, + D. R. Commander. + * Copyright (C) 2015, Google, Inc. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +/* NOTE: This header file does not include stdio.h, despite the fact that it + * uses FILE and size_t. That is by design, since the libjpeg API predates the + * widespread adoption of ANSI/ISO C. Referring to libjpeg.txt, it is a + * documented requirement that calling programs "include system headers that + * define at least the typedefs FILE and size_t" before including jpeglib.h. + * Technically speaking, changing that requirement by including stdio.h here + * would break backward API compatibility. Please do not file bug reports, + * feature requests, or pull requests regarding this. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +/* NOTE: In lossless mode, an MCU contains one or more samples rather than one + * or more 8x8 DCT blocks, so the term "data unit" is used to generically + * describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To + * preserve backward API/ABI compatibility, the field and macro names retain + * the "block" terminology. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + */ + +typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples with + 2-bit through 8-bit data precision. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some JSAMPLE rows (a 2-D JSAMPLE + array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D JSAMPLE array: top index is color */ + +typedef J12SAMPLE *J12SAMPROW; /* ptr to one image row of pixel samples + with 9-bit through 12-bit data + precision. */ +typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some J12SAMPLE rows (a 2-D + J12SAMPLE array) */ +typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D J12SAMPLE array: top index is + color */ + +typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of pixel samples + with 13-bit through 16-bit data + precision. */ +typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some J16SAMPLE rows (a 2-D + J16SAMPLE array) */ +typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D J16SAMPLE array: top index is + color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * In lossy mode, any dummy blocks added to complete an MCU are not counted; + * therefore these values do not depend on whether a scan is interleaved or + * not. In lossless mode, these are always equal to the image width and + * height. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a data unit in samples. Always DCTSIZE for lossy compression. + * For lossy decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values from 1 to 16 are supported. Note that different components may + * receive different IDCT scalings. In lossless mode, this is always equal + * to 1. + */ +#if JPEG_LIB_VERSION >= 70 + int DCT_h_scaled_size; + int DCT_v_scaled_size; +#else + int DCT_scaled_size; +#endif + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For lossy decompression, IDCT scaling is + * included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) + * In lossless mode, these are always equal to the image width and height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ + int last_col_width; /* # of non-dummy data units across in last MCU */ + int last_row_height; /* # of non-dummy data units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL *quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void *dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + (Ss is the predictor selection value in + lossless mode) */ + int Ah, Al; /* progressive JPEG successive approx. parms + (Al is the point transform value in lossless + mode) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct *jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET *data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +#define JCS_EXTENSIONS 1 +#define JCS_ALPHA_EXTENSIONS 1 + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue as specified by the RGB_RED, + RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_EXT_RGB, /* red/green/blue */ + JCS_EXT_RGBX, /* red/green/blue/x */ + JCS_EXT_BGR, /* blue/green/red */ + JCS_EXT_BGRX, /* blue/green/red/x */ + JCS_EXT_XBGR, /* x/blue/green/red */ + JCS_EXT_XRGB, /* x/red/green/blue */ + /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, + or JCS_EXT_XRGB during decompression, the X byte is undefined, and in + order to ensure the best performance, libjpeg-turbo can set that byte to + whatever value it wishes. Use the following colorspace constants to + ensure that the X byte is set to 0xFF, so that it can be interpreted as an + opaque alpha channel. */ + JCS_EXT_RGBA, /* red/green/blue/alpha */ + JCS_EXT_BGRA, /* blue/green/red/alpha */ + JCS_EXT_ABGR, /* alpha/blue/green/red */ + JCS_EXT_ARGB, /* alpha/red/green/blue */ + JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue + [decompression only] */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* accurate integer method */ + JDCT_IFAST, /* less accurate integer method [legacy feature] */ + JDCT_FLOAT /* floating-point method [legacy feature] */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr *err; /* Error handler module */ \ + struct jpeg_memory_mgr *mem; /* Memory manager module */ \ + struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \ + void *client_data; /* Available for use by application */ \ + boolean is_decompressor; /* So common code can tell which is which */ \ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct *j_common_ptr; +typedef struct jpeg_compress_struct *j_compress_ptr; +typedef struct jpeg_decompress_struct *j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr *dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + +#if JPEG_LIB_VERSION >= 70 + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ +#endif + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; +#if JPEG_LIB_VERSION >= 70 + int q_scale_factor[NUM_QUANT_TBLS]; +#endif + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info *scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ +#if JPEG_LIB_VERSION >= 70 + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ +#endif + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or + difference controller */ + /* The coefficient or difference controller receives data in units of MCU + * rows as defined for fully interleaved scans (whether the JPEG file is + * interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE + * sample rows of each component in an "iMCU" (interleaved MCU) row. In + * lossless mode, total_iMCU_rows is always equal to the image height. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ +#endif + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master *master; + struct jpeg_c_main_controller *main; + struct jpeg_c_prep_controller *prep; + struct jpeg_c_coef_controller *coef; + struct jpeg_marker_writer *marker; + struct jpeg_color_converter *cconvert; + struct jpeg_downsampler *downsample; + struct jpeg_forward_dct *fdct; + struct jpeg_entropy_encoder *entropy; + jpeg_scan_info *script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr *src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array + If data_precision is 12, then this is + actually a J12SAMPARRAY, so callers must + type-cast it in order to read/write 12-bit + samples from/to the array. */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + +#if JPEG_LIB_VERSION >= 80 + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ +#endif + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#else + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient or difference controller's input and output progress is + * measured in units of "iMCU" (interleaved MCU) rows. These are the same as + * MCU rows in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor + * DCT block rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. + * In lossless mode, total_iMCU_rows is always equal to the image height. + */ + + JSAMPLE *sample_range_limit; /* table for fast range-limiting + If data_precision is 9 to 12, then this is + actually a J12SAMPLE pointer, and if + data_precision is 13 to 16, then this is + actually a J16SAMPLE pointer, so callers + must type-cast it in order to read samples + from the array. */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ +#endif + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master *master; + struct jpeg_d_main_controller *main; + struct jpeg_d_coef_controller *coef; + struct jpeg_d_post_controller *post; + struct jpeg_input_controller *inputctl; + struct jpeg_marker_reader *marker; + struct jpeg_entropy_decoder *entropy; + struct jpeg_inverse_dct *idct; + struct jpeg_upsampler *upsample; + struct jpeg_color_deconverter *cconvert; + struct jpeg_color_quantizer *cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + void (*error_exit) (j_common_ptr cinfo); + /* Conditionally emit a trace or warning message */ + void (*emit_message) (j_common_ptr cinfo, int msg_level); + /* Routine that actually outputs a trace or error message */ + void (*output_message) (j_common_ptr cinfo); + /* Format a message string for the most recent JPEG error or message */ + void (*format_message) (j_common_ptr cinfo, char *buffer); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + void (*reset_error_mgr) (j_common_ptr cinfo); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const *jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const *addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + void (*progress_monitor) (j_common_ptr cinfo); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + void (*init_destination) (j_compress_ptr cinfo); + boolean (*empty_output_buffer) (j_compress_ptr cinfo); + void (*term_destination) (j_compress_ptr cinfo); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET *next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + void (*init_source) (j_decompress_ptr cinfo); + boolean (*fill_input_buffer) (j_decompress_ptr cinfo); + void (*skip_input_data) (j_decompress_ptr cinfo, long num_bytes); + boolean (*resync_to_restart) (j_decompress_ptr cinfo, int desired); + void (*term_source) (j_decompress_ptr cinfo); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control *jvirt_sarray_ptr; +typedef struct jvirt_barray_control *jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); + void *(*alloc_large) (j_common_ptr cinfo, int pool_id, + size_t sizeofobject); + /* If cinfo->data_precision is 12 or 16, then this method and the + * access_virt_sarray method actually return a J12SAMPARRAY or a + * J16SAMPARRAY, so callers must type-cast the return value in order to + * read/write 12-bit or 16-bit samples from/to the array. + */ + JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows); + JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows); + jvirt_sarray_ptr (*request_virt_sarray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + jvirt_barray_ptr (*request_virt_barray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + void (*realize_virt_arrays) (j_common_ptr cinfo); + JSAMPARRAY (*access_virt_sarray) (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + JBLOCKARRAY (*access_virt_barray) (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + void (*free_pool) (j_common_ptr cinfo, int pool_id); + void (*self_destruct) (j_common_ptr cinfo); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef boolean (*jpeg_marker_parser_method) (j_decompress_ptr cinfo); + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JPP(arglist) arglist + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version, + size_t structsize); +EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, + size_t structsize); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile); +EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, + unsigned long *outsize); +EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, + const unsigned char *inbuffer, unsigned long insize); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo, + J_COLOR_SPACE colorspace); +EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo); +EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality, + boolean force_baseline); +EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor, + boolean force_baseline); +#if JPEG_LIB_VERSION >= 70 +EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo, + boolean force_baseline); +#endif +EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline); +EXTERN(int) jpeg_quality_scaling(int quality); +EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo, + int predictor_selection_value, + int point_transform); +EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo); +EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo, + boolean write_all_tables); +EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); + +#if JPEG_LIB_VERSION >= 70 +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo); +#endif + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_raw_data(j_compress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION num_lines); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker, + unsigned int datalen); +EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo); + +/* Write ICC profile. See libjpeg.txt for usage information. */ +EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len); + + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo); +EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(void) jpeg12_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_raw_data(j_decompress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION max_lines); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number); +EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo); +EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo); +EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +#if JPEG_LIB_VERSION >= 80 +EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo); +#endif +EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo, + int marker_code, + jpeg_marker_parser_method routine); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo); +EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo, + jvirt_barray_ptr *coef_arrays); +EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, + j_compress_ptr dstinfo); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort(j_common_ptr cinfo); +EXTERN(void) jpeg_destroy(j_common_ptr cinfo); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired); + +/* Read ICC profile. See libjpeg.txt for usage information. */ +EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Buffer.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Buffer.hh new file mode 100644 index 0000000..eaa84c9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Buffer.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef BUFFER_HH +#define BUFFER_HH + +#include + +#include +#include +#include +#include + +class Buffer +{ + public: + QPDF_DLL + Buffer(); + + // Create a Buffer object whose memory is owned by the class and will be freed when the Buffer + // object is destroyed. + QPDF_DLL + Buffer(size_t size); + QPDF_DLL + Buffer(std::string&& content); + + // Create a Buffer object whose memory is owned by the caller and will not be freed when the + // Buffer is destroyed. + QPDF_DLL + Buffer(unsigned char* buf, size_t size); + QPDF_DLL + Buffer(std::string& content); + + Buffer(Buffer const&) = delete; + Buffer& operator=(Buffer const&) = delete; + + QPDF_DLL + Buffer(Buffer&&) noexcept; + QPDF_DLL + Buffer& operator=(Buffer&&) noexcept; + QPDF_DLL + ~Buffer(); + QPDF_DLL + size_t getSize() const; + QPDF_DLL + unsigned char const* getBuffer() const; + QPDF_DLL + unsigned char* getBuffer(); + + // Create a new copy of the Buffer. The new Buffer owns an independent copy of the data. + QPDF_DLL + Buffer copy() const; + + // Move the content of the Buffer. After calling this method, the Buffer will be empty if the + // buffer owns its memory. Otherwise, the Buffer will be unchanged. + QPDF_DLL + std::string move(); + + // Return a string_view to the data. + QPDF_DLL + std::string_view view() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char const* data() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char* data(); + + QPDF_DLL + bool empty() const; + + QPDF_DLL + size_t size() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/BufferInputSource.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/BufferInputSource.hh new file mode 100644 index 0000000..0b857b8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/BufferInputSource.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_BUFFERINPUTSOURCE_HH +#define QPDF_BUFFERINPUTSOURCE_HH + +#include +#include + +#include + +class QPDF_DLL_CLASS BufferInputSource: public InputSource +{ + public: + // If own_memory is true, BufferInputSource will delete the buffer when finished with it. + // Otherwise, the caller owns the memory. + QPDF_DLL + BufferInputSource(std::string const& description, Buffer* buf, bool own_memory = false); + + // NB This overload copies the string contents. + QPDF_DLL + BufferInputSource(std::string const& description, std::string const& contents); + QPDF_DLL + ~BufferInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: +#ifndef QPDF_FUTURE + bool own_memory; + std::string description; + Buffer* buf; + qpdf_offset_t cur_offset; + qpdf_offset_t max_offset; +#else + class Members; + + std::unique_ptr m; +#endif +}; + +#endif // QPDF_BUFFERINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/ClosedFileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/ClosedFileInputSource.hh new file mode 100644 index 0000000..56b2cb1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/ClosedFileInputSource.hh @@ -0,0 +1,77 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_CLOSEDFILEINPUTSOURCE_HH +#define QPDF_CLOSEDFILEINPUTSOURCE_HH + +#include + +#include + +class FileInputSource; + +// This is an input source that reads from files, like FileInputSource, except that it opens and +// closes the file surrounding every operation. This decreases efficiency, but it allows many more +// of these to exist at once than the maximum number of open file descriptors. This is used for +// merging large numbers of files. +class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource +{ + public: + QPDF_DLL + ClosedFileInputSource(char const* filename); + + ClosedFileInputSource(ClosedFileInputSource const&) = delete; + ClosedFileInputSource& operator=(ClosedFileInputSource const&) = delete; + + QPDF_DLL + ~ClosedFileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + // The file stays open between calls to stayOpen(true) and stayOpen(false). You can use this to + // surround multiple operations on a single ClosedFileInputSource to reduce the overhead of a + // separate open/close on each call. + QPDF_DLL + void stayOpen(bool); + + private: + QPDF_DLL_PRIVATE + void before(); + QPDF_DLL_PRIVATE + void after(); + + std::string filename; + qpdf_offset_t offset{0}; + std::shared_ptr fis; + bool stay_open{false}; +}; + +#endif // QPDF_CLOSEDFILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Constants.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Constants.h new file mode 100644 index 0000000..4b32713 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Constants.h @@ -0,0 +1,297 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFCONSTANTS_H +#define QPDFCONSTANTS_H + +/* + * REMEMBER: + * + * Keep this file 'C' compatible so it can be used from the C and C++ + * interfaces. + */ + +/* ****************************** NOTE ****************************** + +Tl;Dr: new values must be added to the end such that no constant's +numerical value changes, even across major releases. + +Details: + +As new values are added to existing enumerated types in this file, +it is important not to change the actual values of any constants. +This means that, in the absence of explicit assignment of values, +the order of entries can't change even across major releases. Why? +Here are the reasons: + +* Many of these constants are used by the C API. The C API is used + through foreign function call interfaces by users of other languages + who may not have access to or the ability to parse a C header file. + As such, users are likely to hard-code numerical values or create + their own constants whose values match. If we change values here, + their code would break, and there would be no way to detect it short + of noticing a bug. Furthermore, it would be difficult to write code + that properly handled more than one version of the qpdf shared + object (e.g. DLL) since the information about what version of qpdf + is involved is only available at runtime. + +- It has happened from time to time that a user builds an application + with an incorrectly installed qpdf, such as having mismatched header + files and library files. In the event that they are only using qpdf + interfaces that have been stable across the versions in question, + this turns out to be harmless. If they happen to use non-compatible + interfaces, this results usually in a failure to load or an obvious + runtime error. If we change values of constants, it is possible that + code that links and runs may have mismatched values for constants. + This would create a bug that would be extremely difficult to track + down and impossible for qpdf maintainers to reproduce. + +*/ + +/* Exit Codes from QPDFJob and the qpdf CLI */ + +enum qpdf_exit_code_e { + qpdf_exit_success = 0, + /* Normal exit codes */ + qpdf_exit_error = 2, + qpdf_exit_warning = 3, + /* For --is-encrypted and --requires-password */ + qpdf_exit_is_not_encrypted = 2, + qpdf_exit_correct_password = 3, +}; + +/* Error Codes */ + +enum qpdf_error_code_e { + qpdf_e_success = 0, + qpdf_e_internal, /* logic/programming error -- indicates bug */ + qpdf_e_system, /* I/O error, memory error, etc. */ + qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */ + qpdf_e_password, /* incorrect password for encrypted file */ + qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */ + qpdf_e_pages, /* erroneous or unsupported pages structure */ + qpdf_e_object, /* type/bounds errors accessing objects */ + qpdf_e_json, /* error in qpdf JSON */ + qpdf_e_linearization, /* linearization warning */ +}; + +/* Object Types */ + +/* PDF objects represented by QPDFObjectHandle or, in the C API, by + * qpdf_oh, have a unique type code that has one of the values in the + * list below. As new object types are added to qpdf, additional items + * may be added to the list, so code that switches on these values + * should take that into consideration. (Maintainer note: it would be + * better to call this qpdf_ot_* rather than ot_* to reduce likelihood + * of name collision, but changing the names of the values breaks + * backward compatibility.) + */ +enum qpdf_object_type_e { + /* Object types internal to qpdf */ + ot_uninitialized, + ot_reserved, + /* Object types that can occur in the main document */ + ot_null, + ot_boolean, + ot_integer, + ot_real, + ot_string, + ot_name, + ot_array, + ot_dictionary, + ot_stream, + /* Additional object types that can occur in content streams */ + ot_operator, + ot_inlineimage, + /* Object types internal to qpdf */ + ot_unresolved, + ot_destroyed, + ot_reference, +}; + +/* Write Parameters. See QPDFWriter.hh for details. */ + +enum qpdf_object_stream_e { + qpdf_o_disable = 0, /* disable object streams */ + qpdf_o_preserve, /* preserve object streams */ + qpdf_o_generate /* generate object streams */ +}; +enum qpdf_stream_data_e { + qpdf_s_uncompress = 0, /* uncompress stream data */ + qpdf_s_preserve, /* preserve stream data compression */ + qpdf_s_compress /* compress stream data */ +}; + +/* Stream data flags */ + +/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */ +enum qpdf_stream_encode_flags_e { + qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */ + qpdf_ef_normalize = 1 << 1, /* normalize content stream */ +}; +enum qpdf_stream_decode_level_e { + /* These must be in order from less to more decoding. */ + qpdf_dl_none = 0, /* preserve all stream filters */ + qpdf_dl_generalized, /* decode general-purpose filters */ + qpdf_dl_specialized, /* also decode other non-lossy filters */ + qpdf_dl_all /* also decode lossy filters */ +}; +/* For JSON encoding */ +enum qpdf_json_stream_data_e { + qpdf_sj_none = 0, + qpdf_sj_inline, + qpdf_sj_file, +}; + +/* R3 Encryption Parameters */ + +enum qpdf_r3_print_e { + qpdf_r3p_full = 0, /* allow all printing */ + qpdf_r3p_low, /* allow only low-resolution printing */ + qpdf_r3p_none /* allow no printing */ +}; + +/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It + * corresponds to options in Acrobat 5's menus. The new interface in + * QPDFWriter offers more granularity and no longer uses this type. + */ +enum qpdf_r3_modify_e /* Allowed changes: */ +{ + qpdf_r3m_all = 0, /* All editing */ + qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */ + qpdf_r3m_form, /* Fill forms, signing, assembly */ + qpdf_r3m_assembly, /* Only document assembly */ + qpdf_r3m_none /* No modifications */ +}; + +/* Form field flags from the PDF spec */ + +enum pdf_form_field_flag_e { + /* flags that apply to all form fields */ + ff_all_read_only = 1 << 0, + ff_all_required = 1 << 1, + ff_all_no_export = 1 << 2, + + /* flags that apply to fields of type /Btn (button) */ + ff_btn_no_toggle_off = 1 << 14, + ff_btn_radio = 1 << 15, + ff_btn_pushbutton = 1 << 16, + ff_btn_radios_in_unison = 1 << 17, + + /* flags that apply to fields of type /Tx (text) */ + ff_tx_multiline = 1 << 12, + ff_tx_password = 1 << 13, + ff_tx_file_select = 1 << 20, + ff_tx_do_not_spell_check = 1 << 22, + ff_tx_do_not_scroll = 1 << 23, + ff_tx_comb = 1 << 24, + ff_tx_rich_text = 1 << 25, + + /* flags that apply to fields of type /Ch (choice) */ + ff_ch_combo = 1 << 17, + ff_ch_edit = 1 << 18, + ff_ch_sort = 1 << 19, + ff_ch_multi_select = 1 << 21, + ff_ch_do_not_spell_check = 1 << 22, + ff_ch_commit_on_sel_change = 1 << 26 +}; + +/* Annotation flags from the PDF spec */ + +enum pdf_annotation_flag_e { + an_invisible = 1 << 0, + an_hidden = 1 << 1, + an_print = 1 << 2, + an_no_zoom = 1 << 3, + an_no_rotate = 1 << 4, + an_no_view = 1 << 5, + an_read_only = 1 << 6, + an_locked = 1 << 7, + an_toggle_no_view = 1 << 8, + an_locked_contents = 1 << 9 +}; + +/* Encryption/password status for QPDFJob */ +enum qpdf_encryption_status_e { qpdf_es_encrypted = 1 << 0, qpdf_es_password_incorrect = 1 << 1 }; + +/* Page label types */ +enum qpdf_page_label_e { + pl_none, + pl_digits, + pl_alpha_lower, + pl_alpha_upper, + pl_roman_lower, + pl_roman_upper, +}; + +/** + * @enum qpdf_result_e + * @brief Enum representing result codes for qpdf C-API functions. + * + * Results <= qpdf_r_no_warn indicate success without warnings, + * qpdf_r_no_warn < result <= qpdf_r_success indicates success with warnings, and + * qpdf_r_success < result indicates failure. + */ +enum qpdf_result_e { + /* success */ + qpdf_r_ok = 0, + qpdf_r_no_warn = 0xff, /// any result <= qpdf_no_warn indicates success without warning + qpdf_r_success = 0xffff, /// any result <= qpdf_r_success indicates success + /* failure */ + qpdf_r_bad_parameter = 0x10000, + + qpdf_r_no_warn_mask = 0x7fffff00, + qpdf_r_success_mask = 0x7fff0000, +}; + +/** + * @enum qpdf_param_e + * @brief This enumeration defines various parameters and configuration options for qpdf C-API + * functions. + * + * The enum values are grouped into sections based on their functionality, such as global + * options or global limits. For the meaning of individual parameters see `qpdf/global.cc` + */ +enum qpdf_param_e { + /* global state */ + qpdf_p_limit_errors = 0x10020, + + /* global options */ + qpdf_p_inspection_mode = 0x11000, + qpdf_p_default_limits = 0x11100, + /* global limits */ + + /* parser limits */ + qpdf_p_parser_max_nesting = 0x13000, + qpdf_p_parser_max_errors, + qpdf_p_parser_max_container_size, + qpdf_p_parser_max_container_size_damaged, + + /* stream and filter limits */ + qpdf_p_max_stream_filters = 0x14000, + + /* next section = 0x20000 */ + qpdf_enum_max = 0x7fffffff, +}; + +#endif /* QPDFCONSTANTS_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/DLL.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/DLL.h new file mode 100644 index 0000000..cc6dcbb --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/DLL.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDF_DLL_HH +#define QPDF_DLL_HH + +/* The first version of qpdf to include the version constants is 10.6.0. */ +#define QPDF_MAJOR_VERSION 12 +#define QPDF_MINOR_VERSION 3 +#define QPDF_PATCH_VERSION 2 + +#ifdef QPDF_FUTURE +# define QPDF_VERSION "12.3.2+future" +#else +# define QPDF_VERSION "12.3.2" +#endif + +/* + * This file defines symbols that control the which functions, + * classes, and methods are exposed to the public ABI (application + * binary interface). See below for a detailed explanation. + */ + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef libqpdf_EXPORTS +# define QPDF_DLL __declspec(dllexport) +# else +# define QPDF_DLL +# endif +# define QPDF_DLL_PRIVATE +#elif defined __GNUC__ +# define QPDF_DLL __attribute__((visibility("default"))) +# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden"))) +#else +# define QPDF_DLL +# define QPDF_DLL_PRIVATE +#endif +#ifdef __GNUC__ +# define QPDF_DLL_CLASS QPDF_DLL +#else +# define QPDF_DLL_CLASS +#endif + +/* + +Here's what's happening. See also https://gcc.gnu.org/wiki/Visibility +for a more in-depth discussion. + +* Everything in the public ABI must be exported. Things not in the + public ABI should not be exported. + +* A class's runtime type information is need if the class is going to + be used as an exception, inherited from, or tested with + dynamic_class. To do these things across a shared object boundary, + runtime type information must be exported. + +* On Windows: + + * For a symbol (function, method, etc.) to be exported into the + public ABI, it must be explicitly marked for export. + + * If you mark a class for export, all symbols in the class, + including private methods, are exported into the DLL, and there is + no way to exclude something from export. + + * A class's run-time type information is made available based on the + presence of a compiler flag (with MSVC), which is always on for + qpdf builds. + + * Marking classes for export should be done only when *building* the + DLL, not when *using* the DLL. + + * It is possible to mark symbols for import for DLL users, but it is + not necessary, and doing it right is complex in our case of being + multi-platform and building both static and shared libraries that + use the same headers, so we don't bother. + + * If we don't export base classes with mingw, the vtables don't end + up in the DLL. + +* On Linux (and other similar systems): + + * Common compilers such as gcc and clang export all symbols into the + public ABI by default. The qpdf build overrides this by using + "visibility=hidden", which makes it behave more like Windows in + that things have to be explicitly exported to appear in the public + ABI. + + * As with Windows, marking a class for export causes everything in + the class, including private methods, the be exported. However, + unlike in Windows: + + * It is possible to explicitly mark symbols as private + + * The only way to get the runtime type and vtable information into + the ABI is to mark the class as exported. + + * It is harmless and sometimes necessary to include the visibility + marks when using the library as well as when building it. In + particular, clang on MacOS requires the visibility marks to + match in both cases. + +What does this mean: + +* On Windows, we never have to export a class, and while there is no + way to "unexport" something, we also have no need to do it. + +* On non-Windows, we have to export some classes, and when we do, we + have to "unexport" some of their parts. + +* We only use the libqpdf_EXPORTS as a conditional for defining the + symbols for Windows builds. + +To achieve this, we use QPDF_DLL_CLASS to export classes, QPDF_DLL to +export methods, and QPDF_DLL_PRIVATE to unexport private methods in +exported classes. + +*/ + +#endif /* QPDF_DLL_HH */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/FileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/FileInputSource.hh new file mode 100644 index 0000000..af42400 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/FileInputSource.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_FILEINPUTSOURCE_HH +#define QPDF_FILEINPUTSOURCE_HH + +#include + +class QPDF_DLL_CLASS FileInputSource: public InputSource +{ + public: + FileInputSource() = default; + QPDF_DLL + FileInputSource(char const* filename); + QPDF_DLL + FileInputSource(char const* description, FILE* filep, bool close_file); + QPDF_DLL + void setFilename(char const* filename); + QPDF_DLL + void setFile(char const* description, FILE* filep, bool close_file); + + FileInputSource(FileInputSource const&) = delete; + FileInputSource& operator=(FileInputSource const&) = delete; + + QPDF_DLL + ~FileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: + bool close_file{false}; + std::string filename; + FILE* file{nullptr}; +}; + +#endif // QPDF_FILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/InputSource.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/InputSource.hh new file mode 100644 index 0000000..bac54ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/InputSource.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_INPUTSOURCE_HH +#define QPDF_INPUTSOURCE_HH + +#include +#include + +#include +#include +#include + +// Remember to use QPDF_DLL_CLASS on anything derived from InputSource so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS InputSource +{ + public: + InputSource() = default; + + virtual ~InputSource() = default; + + class QPDF_DLL_CLASS Finder + { + public: + QPDF_DLL + Finder() = default; + QPDF_DLL + virtual ~Finder() = default; + virtual bool check() = 0; + }; + + QPDF_DLL + void setLastOffset(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getLastOffset() const; + QPDF_DLL + std::string readLine(size_t max_line_length); + + // Find first or last occurrence of a sequence of characters starting within the range defined + // by offset and len such that, when the input source is positioned at the beginning of that + // sequence, finder.check() returns true. If len is 0, the search proceeds until EOF. If a + // qualifying pattern is found, these methods return true and leave the input source positioned + // wherever check() left it at the end of the matching pattern. + QPDF_DLL + bool findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + QPDF_DLL + bool findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + + virtual qpdf_offset_t findAndSkipNextEOL() = 0; + virtual std::string const& getName() const = 0; + virtual qpdf_offset_t tell() = 0; + virtual void seek(qpdf_offset_t offset, int whence) = 0; + virtual void rewind() = 0; + virtual size_t read(char* buffer, size_t length) = 0; + + // Note: you can only unread the character you just read. The specific character is ignored by + // some implementations, and the implementation doesn't check this. Use of unreadCh is + // semantically equivalent to seek(-1, SEEK_CUR) but is much more efficient. + virtual void unreadCh(char ch) = 0; + + // The following methods are for internal use by qpdf only. + inline size_t read(std::string& str, size_t count, qpdf_offset_t at = -1); + inline std::string read(size_t count, qpdf_offset_t at = -1); + size_t read_line(std::string& str, size_t count, qpdf_offset_t at = -1); + std::string read_line(size_t count, qpdf_offset_t at = -1); + inline qpdf_offset_t fastTell(); + inline bool fastRead(char&); + inline void fastUnread(bool); + inline void loadBuffer(); + + protected: + qpdf_offset_t last_offset{0}; + + private: + // State for fast... methods + static const qpdf_offset_t buf_size = 128; + char buffer[buf_size]; + qpdf_offset_t buf_len = 0; + qpdf_offset_t buf_idx = 0; + qpdf_offset_t buf_start = 0; +}; + +#endif // QPDF_INPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/JSON.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/JSON.hh new file mode 100644 index 0000000..3713e73 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/JSON.hh @@ -0,0 +1,404 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef JSON_HH +#define JSON_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Pipeline; +class InputSource; + +// This is a simple JSON serializer and parser, primarily designed for serializing QPDF Objects as +// JSON. While it may work as a general-purpose JSON parser/serializer, there are better options. +// JSON objects contain their data as smart pointers. When one JSON object is added to another, this +// pointer is copied. This means you can create temporary JSON objects on the stack, add them to +// other objects, and let them go out of scope safely. It also means that if a JSON object is added +// in more than one place, all copies share the underlying data. This makes them similar in +// structure and behavior to QPDFObjectHandle and may feel natural within the QPDF codebase, but it +// is also a good reason not to use this as a general-purpose JSON package. +class JSON +{ + public: + static int constexpr LATEST = 2; + + JSON() = default; + + QPDF_DLL + std::string unparse() const; + + // Write the JSON object through a pipeline. The `depth` parameter specifies how deeply nested + // this is in another JSON structure, which makes it possible to write clean-looking JSON + // incrementally. + QPDF_DLL + void write(Pipeline*, size_t depth = 0) const; + + // Helper methods for writing JSON incrementally. + // + // "first" -- Several methods take a `bool& first` parameter. The open methods always set it to + // true, and the methods to output items always set it to false. This way, the item and close + // methods can always know whether or not a first item is being written. The intended mode of + // operation is to start with a new `bool first = true` each time a new container is opened and + // to pass that `first` through to all the methods that are called to add top-level items to the + // container as well as to close the container. This lets the JSON object use it to keep track + // of when it's writing a first object and when it's not. If incrementally writing multiple + // levels of depth, a new `first` should be used for each new container that is opened. + // + // "depth" -- Indicate the level of depth. This is used for consistent indentation. When writing + // incrementally, whenever you call a method to add an item to a container, the value of `depth` + // should be one more than whatever value is passed to the container open and close methods. + + // Open methods ignore the value of first and set it to false + QPDF_DLL + static void writeDictionaryOpen(Pipeline*, bool& first, size_t depth = 0); + QPDF_DLL + static void writeArrayOpen(Pipeline*, bool& first, size_t depth = 0); + // Close methods don't modify first. A true value indicates that we are closing an empty object. + QPDF_DLL + static void writeDictionaryClose(Pipeline*, bool first, size_t depth = 0); + QPDF_DLL + static void writeArrayClose(Pipeline*, bool first, size_t depth = 0); + // The item methods use the value of first to determine if this is the first item and always set + // it to false. + QPDF_DLL + static void writeDictionaryItem( + Pipeline*, bool& first, std::string const& key, JSON const& value, size_t depth = 0); + // Write just the key of a new dictionary item, useful if writing nested structures. Calls + // writeNext. + QPDF_DLL + static void + writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth = 0); + QPDF_DLL + static void writeArrayItem(Pipeline*, bool& first, JSON const& element, size_t depth = 0); + // If writing nested structures incrementally, call writeNext before opening a new array or + // container in the midst of an existing one. The `first` you pass to writeNext should be the + // one for the parent object. The depth should be the one for the child object. Then start a new + // `first` for the nested item. Note that writeDictionaryKey and writeArrayItem call writeNext + // for you, so this is most important when writing subsequent items or container openers to an + // array. + QPDF_DLL + static void writeNext(Pipeline* p, bool& first, size_t depth = 0); + + // The JSON spec calls dictionaries "objects", but that creates too much confusion when + // referring to instances of the JSON class. + QPDF_DLL + static JSON makeDictionary(); + // addDictionaryMember returns the newly added item. + QPDF_DLL + JSON addDictionaryMember(std::string const& key, JSON const&); + QPDF_DLL + static JSON makeArray(); + // addArrayElement returns the newly added item. + QPDF_DLL + JSON addArrayElement(JSON const&); + QPDF_DLL + static JSON makeString(std::string const& utf8); + QPDF_DLL + static JSON makeInt(long long int value); + QPDF_DLL + static JSON makeReal(double value); + QPDF_DLL + static JSON makeNumber(std::string const& encoded); + QPDF_DLL + static JSON makeBool(bool value); + QPDF_DLL + static JSON makeNull(); + + // A blob serializes as a string. The function will be called by JSON with a pipeline and should + // write binary data to the pipeline but not call finish(). JSON will call finish() at the right + // time. + QPDF_DLL + static JSON makeBlob(std::function); + + QPDF_DLL + bool isArray() const; + + QPDF_DLL + bool isDictionary() const; + + // Accessors. Accessor behavior: + // + // - If argument is wrong type, including null, return false + // - If argument is right type, return true and initialize the value + + QPDF_DLL + bool getString(std::string& utf8) const; + QPDF_DLL + bool getNumber(std::string& value) const; + QPDF_DLL + bool getBool(bool& value) const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + JSON getDictItem(std::string const& key) const; + QPDF_DLL + bool forEachDictItem(std::function fn) const; + QPDF_DLL + bool forEachArrayItem(std::function fn) const; + + // Check this JSON object against a "schema". This is not a schema according to any standard. + // It's just a template of what the JSON is supposed to contain. The checking does the + // following: + // + // * The schema is a nested structure containing dictionaries, single-element arrays, and + // strings only. + // * Recursively walk the schema. In the items below, "schema object" refers to an object in + // the schema, and "checked object" refers to the corresponding part of the object being + // checked. + // * If the schema object is a dictionary, the checked object must have a dictionary in the + // same place with the same keys. If flags contains f_optional, a key in the schema does not + // have to be present in the object. Otherwise, all keys have to be present. Any key in the + // object must be present in the schema. + // * If the schema object is an array of length 1, the checked object may either be a single + // item or an array of items. The single item or each element of the checked object's + // array is validated against the single element of the schema's array. The rationale behind + // this logic is that a single element may appear wherever the schema allows a + // variable-length array. This makes it possible to start allowing an array in the future + // where a single element was previously required without breaking backward compatibility. + // * If the schema object is an array of length > 1, the checked object must be an array of + // the same length. In this case, each element of the checked object array is validated + // against the corresponding element of the schema array. + // * Otherwise, the value must be a string whose value is a description of the object's + // corresponding value, which may have any type. + // + // QPDF's JSON output conforms to certain strict compatibility rules as discussed in the manual. + // The idea is that a JSON structure created manually in qpdf.cc doubles as both JSON help + // information and a schema for validating the JSON that qpdf generates. Any discrepancies are a + // bug in qpdf. + // + // Flags is a bitwise or of values from check_flags_e. + enum check_flags_e { + f_none = 0, + f_optional = 1 << 0, + }; + QPDF_DLL + bool checkSchema(JSON schema, unsigned long flags, std::list& errors); + + // Same as passing 0 for flags + QPDF_DLL + bool checkSchema(JSON schema, std::list& errors); + + // A pointer to a Reactor class can be passed to parse, which will enable the caller to react + // to incremental events in the construction of the JSON object. This makes it possible to + // implement SAX-like handling of very large JSON objects. + class QPDF_DLL_CLASS Reactor + { + public: + virtual ~Reactor() = default; + + // The start/end methods are called when parsing of a dictionary or array is started or + // ended. The item methods are called when an item is added to a dictionary or array. When + // adding a container to another container, the item method is called with an empty + // container before the lower container's start method is called. See important notes in + // "Item methods" below. + + // During parsing of a JSON string, the parser is operating on a single object at a time. + // When a dictionary or array is started, a new context begins, and when that dictionary or + // array is ended, the previous context is resumed. So, for + // example, if you have `{"a": [1]}`, you will receive the + // following method calls + // + // dictionaryStart -- current object is the top-level dictionary + // dictionaryItem -- called with "a" and an empty array + // arrayStart -- current object is the array + // arrayItem -- called with the "1" object + // containerEnd -- now current object is the dictionary again + // containerEnd -- current object is undefined + // + // If the top-level item in a JSON string is a scalar, the topLevelScalar() method will be + // called. No argument is passed since the object is the same as what is returned by + // parse(). + + QPDF_DLL + virtual void dictionaryStart() = 0; + QPDF_DLL + virtual void arrayStart() = 0; + QPDF_DLL + virtual void containerEnd(JSON const& value) = 0; + QPDF_DLL + virtual void topLevelScalar() = 0; + + // Item methods: + // + // The return value of the item methods indicate whether the item has been "consumed". If + // the item method returns true, then the item will not be added to the containing JSON + // object. This is what allows arbitrarily large JSON objects + // to be parsed and not have to be kept in memory. + // + // NOTE: When a dictionary or an array is added to a container, the dictionaryItem or + // arrayItem method is called when the child item's start delimiter is encountered, so the + // JSON object passed in at that time will always be in its initial, empty state. + // Additionally, the child item's start method is not called until after the parent item's + // item method is called. This makes it possible to keep track of the current depth level by + // incrementing level on start methods and decrementing on end methods. + + QPDF_DLL + virtual bool dictionaryItem(std::string const& key, JSON const& value) = 0; + QPDF_DLL + virtual bool arrayItem(JSON const& value) = 0; + }; + + // Create a JSON object from a string. + QPDF_DLL + static JSON parse(std::string const&); + // Create a JSON object from an input source. See above for information about how to use the + // Reactor. + QPDF_DLL + static JSON parse(InputSource&, Reactor* reactor = nullptr); + + // parse calls setOffsets to set the inclusive start and non-inclusive end offsets of an object + // relative to its input string. Otherwise, both values are 0. + QPDF_DLL + void setStart(qpdf_offset_t); + QPDF_DLL + void setEnd(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getStart() const; + QPDF_DLL + qpdf_offset_t getEnd() const; + + // The following class does not form part of the public API and is for internal use only. + + class Writer; + + private: + static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter); + + enum value_type_e { + vt_none, + vt_dictionary, + vt_array, + vt_string, + vt_number, + vt_bool, + vt_null, + vt_blob, + }; + + struct JSON_value + { + JSON_value(value_type_e type_code) : + type_code(type_code) + { + } + virtual ~JSON_value() = default; + virtual void write(Pipeline*, size_t depth) const = 0; + const value_type_e type_code{vt_none}; + }; + struct JSON_dictionary: public JSON_value + { + JSON_dictionary() : + JSON_value(vt_dictionary) + { + } + ~JSON_dictionary() override = default; + void write(Pipeline*, size_t depth) const override; + std::map members; + }; + struct JSON_array; + struct JSON_string: public JSON_value + { + JSON_string(std::string const& utf8); + ~JSON_string() override = default; + void write(Pipeline*, size_t depth) const override; + std::string utf8; + }; + struct JSON_number: public JSON_value + { + JSON_number(long long val); + JSON_number(double val); + JSON_number(std::string const& val); + ~JSON_number() override = default; + void write(Pipeline*, size_t depth) const override; + std::string encoded; + }; + struct JSON_bool: public JSON_value + { + JSON_bool(bool val); + ~JSON_bool() override = default; + void write(Pipeline*, size_t depth) const override; + bool value; + }; + struct JSON_null: public JSON_value + { + JSON_null() : + JSON_value(vt_null) + { + } + ~JSON_null() override = default; + void write(Pipeline*, size_t depth) const override; + }; + struct JSON_blob: public JSON_value + { + JSON_blob(std::function fn); + ~JSON_blob() override = default; + void write(Pipeline*, size_t depth) const override; + std::function fn; + }; + + JSON(std::unique_ptr); + + static void checkSchemaInternal( + JSON_value* this_v, + JSON_value* sch_v, + unsigned long flags, + std::list& errors, + std::string prefix); + + class Members + { + friend class JSON; + + public: + ~Members() = default; + + private: + Members(std::unique_ptr); + Members(Members const&) = delete; + + std::unique_ptr value; + // start and end are only populated for objects created by parse + qpdf_offset_t start{0}; + qpdf_offset_t end{0}; + }; + + std::shared_ptr m; +}; + +struct JSON::JSON_array: public JSON_value +{ + JSON_array() : + JSON_value(vt_array) + { + } + ~JSON_array() override = default; + void write(Pipeline*, size_t depth) const override; + std::vector elements; +}; + +#endif // JSON_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/ObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/ObjectHandle.hh new file mode 100644 index 0000000..9cf4dc6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/ObjectHandle.hh @@ -0,0 +1,155 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef OBJECTHANDLE_HH +#define OBJECTHANDLE_HH + +#include +#include +#include + +#include +#include +#include + +#include +#include + +class QPDF; +class QPDF_Dictionary; +class QPDFObject; +class QPDFObjectHandle; + +namespace qpdf +{ + class Array; + class BaseDictionary; + class Dictionary; + class Integer; + class Stream; + + enum typed : std::uint8_t { strict = 0, any_flag = 1, optional = 2, any = 3, error = 4 }; + + // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only + // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, + // QPDFObjGen and bool. + class BaseHandle + { + friend class ::QPDF; + + public: + explicit inline operator bool() const; + inline operator QPDFObjectHandle() const; + QPDF_DLL + operator QPDFObjGen() const; + + // The rest of the header file is for qpdf internal use only. + + // Return true if both object handles refer to the same underlying object. + bool + operator==(BaseHandle const& other) const + { + return obj == other.obj; + } + + // For arrays, return the number of items in the array. + // For null-like objects, return 0. + // For all other objects, return 1. + size_t size() const; + + // Return 'true' if size() == 0. + bool + empty() const + { + return size() == 0; + } + + QPDFObjectHandle operator[](size_t n) const; + QPDFObjectHandle operator[](int n) const; + + QPDFObjectHandle& at(std::string const& key) const; + bool contains(std::string const& key) const; + size_t erase(std::string const& key); + QPDFObjectHandle& find(std::string const& key) const; + bool replace(std::string const& key, QPDFObjectHandle value); + QPDFObjectHandle const& operator[](std::string const& key) const; + + std::shared_ptr copy(bool shallow = false) const; + // Recursively remove association with any QPDF object. This method may only be called + // during final destruction. + void disconnect(bool only_direct = true); + inline QPDFObjGen id_gen() const; + inline bool indirect() const; + inline bool null() const; + inline qpdf_offset_t offset() const; + inline QPDF* qpdf() const; + inline qpdf_object_type_e raw_type_code() const; + inline qpdf_object_type_e resolved_type_code() const; + inline qpdf_object_type_e type_code() const; + std::string unparse() const; + void write_json(int json_version, JSON::Writer& p) const; + static void warn(QPDF*, QPDFExc&&); + void warn(QPDFExc&&) const; + void warn(std::string const& warning) const; + + inline std::shared_ptr const& obj_sp() const; + inline QPDFObjectHandle oh() const; + + protected: + BaseHandle() = default; + BaseHandle(std::shared_ptr const& obj) : + obj(obj) {}; + BaseHandle(std::shared_ptr&& obj) : + obj(std::move(obj)) {}; + BaseHandle(BaseHandle const&) = default; + BaseHandle& operator=(BaseHandle const&) = default; + BaseHandle(BaseHandle&&) = default; + BaseHandle& operator=(BaseHandle&&) = default; + + inline BaseHandle(QPDFObjectHandle const& oh); + inline BaseHandle(QPDFObjectHandle&& oh); + + ~BaseHandle() = default; + + template + T* as() const; + + inline void assign(qpdf_object_type_e required, BaseHandle const& other); + inline void assign(qpdf_object_type_e required, BaseHandle&& other); + + inline void nullify(); + + std::string description() const; + + inline QPDFObjectHandle const& get(std::string const& key) const; + + void no_ci_warn_if(bool condition, std::string const& warning) const; + void no_ci_stop_if(bool condition, std::string const& warning) const; + void no_ci_stop_damaged_if(bool condition, std::string const& warning) const; + std::invalid_argument invalid_error(std::string const& method) const; + std::runtime_error type_error(char const* expected_type) const; + QPDFExc type_error(char const* expected_type, std::string const& message) const; + char const* type_name() const; + + std::shared_ptr obj; + }; + +} // namespace qpdf + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/PDFVersion.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/PDFVersion.hh new file mode 100644 index 0000000..32b1df5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/PDFVersion.hh @@ -0,0 +1,65 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PDFVERSION_HH +#define PDFVERSION_HH + +#include +#include + +// Represent a PDF version. PDF versions are typically major.minor, but PDF 1.7 has several +// extension levels as the ISO 32000 spec was in progress. This class helps with comparison of +// versions. +class PDFVersion +{ + public: + PDFVersion() = default; + PDFVersion(PDFVersion const&) = default; + PDFVersion& operator=(PDFVersion const&) = default; + + QPDF_DLL + PDFVersion(int major, int minor, int extension = 0); + QPDF_DLL + bool operator<(PDFVersion const& rhs) const; + QPDF_DLL + bool operator==(PDFVersion const& rhs) const; + + // Replace this version with the other one if the other one is greater. + QPDF_DLL + void updateIfGreater(PDFVersion const& other); + + // Initialize a string and integer suitable for passing to QPDFWriter::setMinimumPDFVersion or + // QPDFWriter::forcePDFVersion. + QPDF_DLL + void getVersion(std::string& version, int& extension_level) const; + + QPDF_DLL + int getMajor() const; + QPDF_DLL + int getMinor() const; + QPDF_DLL + int getExtensionLevel() const; + + private: + int major_version{0}; + int minor_version{0}; + int extension_level{0}; +}; + +#endif // PDFVERSION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pipeline.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pipeline.hh new file mode 100644 index 0000000..6e07c4f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pipeline.hh @@ -0,0 +1,115 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PIPELINE_HH +#define PIPELINE_HH + +#include + +#include +#include + +// Generalized Pipeline interface. By convention, subclasses of Pipeline are called Pl_Something. +// +// When an instance of Pipeline is created with a pointer to a next pipeline, that pipeline writes +// its data to the next one when it finishes with it. In order to make possible a usage style in +// which a pipeline may be passed to a function which may stick other pipelines in front of it, the +// allocator of a pipeline is responsible for its destruction. In other words, one pipeline object +// does not attempt to manage the memory of its successor. +// +// The client is required to call finish() before destroying a Pipeline in order to avoid loss of +// data. A Pipeline class should not throw an exception in the destructor if this hasn't been done +// though since doing so causes too much trouble when deleting pipelines during error conditions. +// +// Some pipelines are reusable (i.e., you can call write() after calling finish() and can call +// finish() multiple times) while others are not. It is up to the caller to use a pipeline +// according to its own restrictions. +// +// Remember to use QPDF_DLL_CLASS on anything derived from Pipeline so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS Pipeline +{ + public: + QPDF_DLL + Pipeline(char const* identifier, Pipeline* next); + + virtual ~Pipeline() = default; + + // Subclasses should implement write and finish to do their jobs and then, if they are not + // end-of-line pipelines, call getNext()->write or getNext()->finish. + QPDF_DLL + virtual void write(unsigned char const* data, size_t len) = 0; + QPDF_DLL + virtual void finish() = 0; + QPDF_DLL + std::string getIdentifier() const; + + // These are convenience methods for making it easier to write certain other types of data to + // pipelines without having to cast. The methods that take char const* expect null-terminated C + // strings and do not write the null terminators. + QPDF_DLL + void writeCStr(char const* cstr); + QPDF_DLL + void writeString(std::string const&); + // This allows *p << "x" << "y" but is not intended to be a general purpose << compatible with + // ostream and does not have local awareness or the ability to be "imbued" with properties. + QPDF_DLL + Pipeline& operator<<(char const* cstr); + QPDF_DLL + Pipeline& operator<<(std::string const&); + QPDF_DLL + Pipeline& operator<<(short); + QPDF_DLL + Pipeline& operator<<(int); + QPDF_DLL + Pipeline& operator<<(long); + QPDF_DLL + Pipeline& operator<<(long long); + QPDF_DLL + Pipeline& operator<<(unsigned short); + QPDF_DLL + Pipeline& operator<<(unsigned int); + QPDF_DLL + Pipeline& operator<<(unsigned long); + QPDF_DLL + Pipeline& operator<<(unsigned long long); + + // Overloaded write to reduce casting + QPDF_DLL + void write(char const* data, size_t len); + + protected: + QPDF_DLL + Pipeline* getNext(bool allow_null = false); + + Pipeline* + next() const noexcept + { + return next_; + } + std::string identifier; + + private: + Pipeline(Pipeline const&) = delete; + Pipeline& operator=(Pipeline const&) = delete; + + Pipeline* next_; +}; + +#endif // PIPELINE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Buffer.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Buffer.hh new file mode 100644 index 0000000..b3b7ed6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Buffer.hh @@ -0,0 +1,76 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_BUFFER_HH +#define PL_BUFFER_HH + +#include +#include + +#include +#include + +// This pipeline accumulates the data passed to it into a memory buffer. Each subsequent use of +// this buffer appends to the data accumulated so far. getBuffer() may be called only after calling +// finish() and before calling any subsequent write(). At that point, a dynamically allocated +// Buffer object is returned and the internal buffer is reset. The caller is responsible for +// deleting the returned Buffer. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it. +class QPDF_DLL_CLASS Pl_Buffer: public Pipeline +{ + public: + QPDF_DLL + Pl_Buffer(char const* identifier, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_Buffer() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + + // Each call to getBuffer() resets this object -- see notes above. + // The caller is responsible for deleting the returned Buffer object. See also + // getBufferSharedPointer() and getMallocBuffer(). + QPDF_DLL + Buffer* getBuffer(); + + // Same as getBuffer but wraps the result in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // getMallocBuffer behaves in the same was as getBuffer except the buffer is allocated with + // malloc(), making it suitable for use when calling from other languages. If there is no data, + // *buf is set to a null pointer and *len is set to 0. Otherwise, *buf is a buffer of size *len + // allocated with malloc(). It is the caller's responsibility to call free() on the buffer. + QPDF_DLL + void getMallocBuffer(unsigned char** buf, size_t* len); + + // Same as getBuffer but returns the result as a string. + QPDF_DLL + std::string getString(); + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Concatenate.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Concatenate.hh new file mode 100644 index 0000000..48a7ca8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Concatenate.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_CONCATENATE_HH +#define PL_CONCATENATE_HH + +#include + +// This pipeline will drop all regular finish calls rather than passing them onto next. To finish +// downstream streams, call manualFinish. This makes it possible to pipe multiple streams (e.g. +// with QPDFObjectHandle::pipeStreamData) to a downstream like Pl_Flate that can't handle multiple +// calls to finish(). +class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline +{ + public: + QPDF_DLL + Pl_Concatenate(char const* identifier, Pipeline* next); + + QPDF_DLL + ~Pl_Concatenate() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + + QPDF_DLL + void finish() override; + + // At the very end, call manualFinish to actually finish the rest of the pipeline. + QPDF_DLL + void manualFinish(); + + private: + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Concatenate; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::unique_ptr m{nullptr}; +}; + +#endif // PL_CONCATENATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Count.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Count.hh new file mode 100644 index 0000000..2189b81 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Count.hh @@ -0,0 +1,52 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_COUNT_HH +#define PL_COUNT_HH + +#include +#include + +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Count: public Pipeline +{ + public: + QPDF_DLL + Pl_Count(char const* identifier, Pipeline* next); + QPDF_DLL + ~Pl_Count() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + // Returns the number of bytes written + QPDF_DLL + qpdf_offset_t getCount() const; + // Returns the last character written, or '\0' if no characters have been written (in which case + // getCount() returns 0) + QPDF_DLL + unsigned char getLastChar() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_COUNT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_DCT.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_DCT.hh new file mode 100644 index 0000000..48f2594 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_DCT.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DCT_HH +#define PL_DCT_HH + +#include + +#include +#include + +// jpeglib.h must be included after cstddef or else it messes up the definition of size_t. +#include + +class QPDF_DLL_CLASS Pl_DCT: public Pipeline +{ + public: + // Constructor for decompressing image data + QPDF_DLL + Pl_DCT(char const* identifier, Pipeline* next); + + // Limit the memory used by jpeglib when decompressing data. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setMemoryLimit(long limit); + + // Limit the number of scans used by jpeglib when decompressing progressive jpegs. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setScanLimit(int limit); + + // Treat corrupt data as a runtime error rather than attempting to decompress regardless. This + // is the qpdf default behaviour. To attempt to decompress corrupt data set 'treat_as_error' to + // false. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setThrowOnCorruptData(bool treat_as_error); + + class QPDF_DLL_CLASS CompressConfig + { + public: + QPDF_DLL + CompressConfig() = default; + QPDF_DLL + virtual ~CompressConfig() = default; + virtual void apply(jpeg_compress_struct*) = 0; + }; + + QPDF_DLL + static std::unique_ptr + make_compress_config(std::function); + + // Constructor for compressing image data + QPDF_DLL + Pl_DCT( + char const* identifier, + Pipeline* next, + JDIMENSION image_width, + JDIMENSION image_height, + int components, + J_COLOR_SPACE color_space, + CompressConfig* config_callback = nullptr); + + QPDF_DLL + ~Pl_DCT() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void compress(void* cinfo); + QPDF_DLL_PRIVATE + void decompress(void* cinfo); + + enum action_e { a_compress, a_decompress }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_DCT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Discard.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Discard.hh new file mode 100644 index 0000000..b0073cd --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Discard.hh @@ -0,0 +1,41 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DISCARD_HH +#define PL_DISCARD_HH + +#include + +// This pipeline discards its output. It is an end-of-line pipeline (with no next). +// +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Discard: public Pipeline +{ + public: + QPDF_DLL + Pl_Discard(); + QPDF_DLL + ~Pl_Discard() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; +}; + +#endif // PL_DISCARD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Flate.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Flate.hh new file mode 100644 index 0000000..2347a91 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Flate.hh @@ -0,0 +1,126 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef PL_FLATE_HH +#define PL_FLATE_HH + +#include +#include +#include +#include +#include + +class QPDF_DLL_CLASS Pl_Flate: public Pipeline +{ + public: + static unsigned int const def_bufsize = 65536; + + enum action_e { a_inflate, a_deflate }; + + QPDF_DLL + Pl_Flate( + char const* identifier, + Pipeline* next, + action_e action, + unsigned int out_bufsize = def_bufsize); + QPDF_DLL + ~Pl_Flate() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_Flate instances. + QPDF_DLL + static unsigned long long memory_limit(); + QPDF_DLL + static void memory_limit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + // Globally set compression level from 1 (fastest, least + // compression) to 9 (slowest, most compression). Use -1 to set + // the default compression level. This is passed directly to zlib. + // This method returns a pointer to the current Pl_Flate object so + // you can create a pipeline with + // Pl_Flate(...)->setCompressionLevel(...) + QPDF_DLL + static void setCompressionLevel(int); + + QPDF_DLL + void setWarnCallback(std::function callback); + + // Returns true if qpdf was built with zopfli support. + QPDF_DLL + static bool zopfli_supported(); + + // Returns true if zopfli is enabled. Zopfli is enabled if QPDF_ZOPFLI is set to a value other + // than "disabled" and zopfli support is compiled in. + QPDF_DLL + static bool zopfli_enabled(); + + // If zopfli is supported, returns true. Otherwise, check the QPDF_ZOPFLI + // environment variable as follows: + // - "disabled" or "silent": return true + // - "force": qpdf_exit_error, throw an exception + // - Any other value: issue a warning, and return false + QPDF_DLL + static bool zopfli_check_env(QPDFLogger* logger = nullptr); + + private: + QPDF_DLL_PRIVATE + void handleData(unsigned char const* data, size_t len, int flush); + QPDF_DLL_PRIVATE + void checkError(char const* prefix, int error_code); + QPDF_DLL_PRIVATE + void warn(char const*, int error_code); + QPDF_DLL_PRIVATE + void finish_zopfli(); + + QPDF_DLL_PRIVATE + static int compression_level; + + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Flate; + + public: + Members(size_t out_bufsize, action_e action); + ~Members(); + + private: + Members(Members const&) = delete; + + std::shared_ptr outbuf; + size_t out_bufsize; + action_e action; + bool initialized; + void* zdata; + unsigned long long written{0}; + std::function callback; + std::unique_ptr zopfli_buf; + }; + + std::unique_ptr m; +}; + +#endif // PL_FLATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Function.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Function.hh new file mode 100644 index 0000000..081a4e1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_Function.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_FUNCTION_HH +#define PL_FUNCTION_HH + +#include + +#include + +// This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can +// be reused. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". +// +// It is okay to keep calling write() after a previous write throws an exception as long as the +// delegated function allows it. +class QPDF_DLL_CLASS Pl_Function: public Pipeline +{ + public: + typedef std::function writer_t; + + // The supplied function is called every time write is called. + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_t fn); + + // The supplied C-style function is called every time write is called. The udata option is + // passed into the function with each call. If the function returns a non-zero value, a runtime + // error is thrown. + typedef int (*writer_c_t)(unsigned char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata); + typedef int (*writer_c_char_t)(char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata); + + QPDF_DLL + ~Pl_Function() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_FUNCTION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_OStream.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_OStream.hh new file mode 100644 index 0000000..0f912f7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_OStream.hh @@ -0,0 +1,50 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_OSTREAM_HH +#define PL_OSTREAM_HH + +#include + +#include + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. +// +// This pipeline is reusable. +class QPDF_DLL_CLASS Pl_OStream: public Pipeline +{ + public: + // os is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_OStream(char const* identifier, std::ostream& os); + QPDF_DLL + ~Pl_OStream() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_OSTREAM_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_QPDFTokenizer.hh new file mode 100644 index 0000000..e26b856 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_QPDFTokenizer.hh @@ -0,0 +1,59 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_QPDFTOKENIZER_HH +#define PL_QPDFTOKENIZER_HH + +#include + +#include +#include +#include + +#include + +// Tokenize the incoming text using QPDFTokenizer and pass the tokens in turn to a +// QPDFObjectHandle::TokenFilter object. All bytes of incoming content will be included in exactly +// one token and passed downstream. +// +// This is a very low-level interface for working with token filters. Most code will want to use +// QPDFObjectHandle::filterPageContents or QPDFObjectHandle::addTokenFilter. See QPDFObjectHandle.hh +// for details. +class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline +{ + public: + // Whatever pipeline is provided as "next" will be set as the pipeline that the token filter + // writes to. If next is not provided, any output written by the filter will be discarded. + QPDF_DLL + Pl_QPDFTokenizer( + char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_QPDFTokenizer() override; + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_RunLength.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_RunLength.hh new file mode 100644 index 0000000..4fc91fa --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_RunLength.hh @@ -0,0 +1,60 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_RUNLENGTH_HH +#define PL_RUNLENGTH_HH + +#include + +class QPDF_DLL_CLASS Pl_RunLength: public Pipeline +{ + public: + enum action_e { a_encode, a_decode }; + + QPDF_DLL + Pl_RunLength(char const* identifier, Pipeline* next, action_e action); + QPDF_DLL + ~Pl_RunLength() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_RunLength instances. + QPDF_DLL + static void setMemoryLimit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void encode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void decode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void flush_encode(); + + enum state_e { st_top, st_copying, st_run }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_RUNLENGTH_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_StdioFile.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_StdioFile.hh new file mode 100644 index 0000000..4c70528 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_StdioFile.hh @@ -0,0 +1,51 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. + +#ifndef PL_STDIOFILE_HH +#define PL_STDIOFILE_HH + +#include + +#include + +// +// This pipeline is reusable. +// +class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline +{ + public: + // f is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_StdioFile(char const* identifier, FILE* f); + QPDF_DLL + ~Pl_StdioFile() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + std::unique_ptr m; +}; + +#endif // PL_STDIOFILE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_String.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_String.hh new file mode 100644 index 0000000..a907b44 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Pl_String.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_STRING_HH +#define PL_STRING_HH + +#include + +#include + +// This pipeline accumulates the data passed to it into a std::string, a reference to which is +// passed in at construction. Each subsequent use of this pipeline appends to the data accumulated +// so far. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". This makes it easy to stick +// this in front of another pipeline to capture data that is written to the other pipeline without +// interfering with when finish is called on the other pipeline and without having to put a +// Pl_Concatenate after it. +class QPDF_DLL_CLASS Pl_String: public Pipeline +{ + public: + QPDF_DLL + Pl_String(char const* identifier, Pipeline* next, std::string& s); + QPDF_DLL + ~Pl_String() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_STRING_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/PointerHolder.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/PointerHolder.hh new file mode 100644 index 0000000..2df2d25 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/PointerHolder.hh @@ -0,0 +1,245 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef POINTERHOLDER_HH +#define POINTERHOLDER_HH + +#define POINTERHOLDER_IS_SHARED_POINTER + +#ifndef POINTERHOLDER_TRANSITION +// 0 = no deprecation warnings, backward-compatible API +// 1 = make PointerHolder(T*) explicit +// 2 = warn for use of getPointer() and getRefcount() +// 3 = warn for all use of PointerHolder +// 4 = don't define PointerHolder at all +# define POINTERHOLDER_TRANSITION 4 +#endif // !defined(POINTERHOLDER_TRANSITION) + +#if POINTERHOLDER_TRANSITION < 4 + +// *** WHAT IS HAPPENING *** + +// In qpdf 11, PointerHolder was replaced with std::shared_ptr +// wherever it appeared in the qpdf API. The PointerHolder object is +// now derived from std::shared_ptr to provide a backward-compatible +// interface and is mutually assignable with std::shared_ptr. Code +// that uses containers of PointerHolder will require adjustment. + +// In qpdf 11, a backward-compatible PointerHolder was provided with a +// warning if POINTERHOLDER_TRANSITION was not defined. Starting in +// qpdf 12, PointerHolder is absent if POINTERHOLDER_TRANSITION is not +// defined. In a future version of qpdf, PointerHolder will be removed +// outright if it becomes inconvenient to keep it around. + +// *** HOW TO TRANSITION *** + +// The symbol POINTERHOLDER_TRANSITION can be defined to help you +// transition your code away from PointerHolder. You can define it +// before including any qpdf header files or including its definition +// in your build configuration. If not defined, it automatically gets +// defined to 4, which excludes PointerHolder entirely. + +// If you want to work gradually to transition your code away from +// PointerHolder, you can define POINTERHOLDER_TRANSITION and fix the +// code so it compiles without warnings and works correctly. If you +// want to be able to continue to support old qpdf versions at the +// same time, you can write code like this: + +// #ifndef POINTERHOLDER_IS_SHARED_POINTER +// ... use PointerHolder as before 10.6 +// #else +// ... use PointerHolder or shared_ptr as needed +// #endif + +// Each level of POINTERHOLDER_TRANSITION exposes differences between +// PointerHolder and std::shared_ptr. The easiest way to transition is +// to increase POINTERHOLDER_TRANSITION in steps of 1 so that you can +// test and handle changes incrementally. + +// POINTERHOLDER_TRANSITION = 1 +// +// PointerHolder has an implicit constructor that takes a T*, so +// you can replace a PointerHolder's pointer by directly assigning +// a T* to it or pass a T* to a function that expects a +// PointerHolder. std::shared_ptr does not have this (risky) +// behavior. When POINTERHOLDER_TRANSITION = 1, PointerHolder's T* +// constructor is declared explicit. For compatibility with +// std::shared_ptr, you can still assign nullptr to a PointerHolder. +// Constructing all your PointerHolder instances explicitly is +// backward compatible, so you can make this change without +// conditional compilation and still use the changes with older qpdf +// versions. +// +// Also defined is a make_pointer_holder method that acts like +// std::make_shared. You can use this as well, but it is not +// compatible with qpdf prior to 10.6 and not necessary with qpdf +// newer than 10.6.3. Like std::make_shared, make_pointer_holder +// can only be used when the constructor implied by its arguments is +// public. If you previously used this, you can replace it width +// std::make_shared now. + +// POINTERHOLDER_TRANSITION = 2 +// +// std::shared_ptr has get() and use_count(). PointerHolder has +// getPointer() and getRefcount(). In 10.6.0, get() and use_count() +// were added as well. When POINTERHOLDER_TRANSITION = 2, getPointer() +// and getRefcount() are deprecated. Fix deprecation warnings by +// replacing with get() and use_count(). This breaks compatibility +// with qpdf older than 10.6. Search for CONST BEHAVIOR for an +// additional note. +// +// Once your code is clean at POINTERHOLDER_TRANSITION = 2, the only +// remaining issues that prevent simple replacement of PointerHolder +// with std::shared_ptr are shared arrays and containers, and neither +// of these are used in the qpdf API. + +// POINTERHOLDER_TRANSITION = 3 +// +// Warn for all use of PointerHolder. This helps you remove all use +// of PointerHolder from your code and use std::shared_ptr instead. +// You will also have to transition any containers of PointerHolder in +// your code. + +// POINTERHOLDER_TRANSITION = 4 +// +// Suppress definition of the PointerHolder type entirely. This is +// the default behavior starting with qpdf 12. + +// CONST BEHAVIOR + +// PointerHolder has had a long-standing bug in its const behavior. +// const PointerHolder's getPointer() method returns a T const*. +// This is incorrect and is not how regular pointers or standard +// library smart pointers behave. Making a PointerHolder const +// should prevent reassignment of its pointer but not affect the thing +// it points to. For that, use PointerHolder. The new get() +// method behaves correctly in this respect and is therefore slightly +// different from getPointer(). This shouldn't break any correctly +// written code. If you are relying on the incorrect behavior, use +// PointerHolder instead. + +# include +# include + +template +class PointerHolder: public std::shared_ptr +{ + public: +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(std::shared_ptr other) : + std::shared_ptr(other) + { + } +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# if POINTERHOLDER_TRANSITION >= 1 + explicit +# endif // POINTERHOLDER_TRANSITION >= 1 +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(T* pointer = 0) : + std::shared_ptr(pointer) + { + } + // Create a shared pointer to an array +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(bool, T* pointer) : + std::shared_ptr(pointer, std::default_delete()) + { + } + + virtual ~PointerHolder() = default; + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T* + getPointer() + { + return this->get(); + } +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T const* + getPointer() const + { + return this->get(); + } + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + int + getRefcount() const + { + return static_cast(this->use_count()); + } + + PointerHolder& + operator=(decltype(nullptr)) + { + std::shared_ptr::operator=(nullptr); + return *this; + } + T const& + operator*() const + { + return *(this->get()); + } + T& + operator*() + { + return *(this->get()); + } + + T const* + operator->() const + { + return this->get(); + } + T* + operator->() + { + return this->get(); + } +}; + +template +inline PointerHolder +make_pointer_holder(_Args&&... __args) +{ + return PointerHolder(new T(__args...)); +} + +template +PointerHolder +make_array_pointer_holder(size_t n) +{ + return PointerHolder(true, new T[n]); +} + +#endif // POINTERHOLDER_TRANSITION < 4 +#endif // POINTERHOLDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QIntC.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QIntC.hh new file mode 100644 index 0000000..cef8aca --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QIntC.hh @@ -0,0 +1,310 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QINTC_HH +#define QINTC_HH + +#include +#include +#include +#include +#include +#include +#include +#include + +// This namespace provides safe integer conversion that detects +// overflows. It uses short, cryptic names for brevity. + +namespace QIntC // QIntC = qpdf Integer Conversion +{ + // to_u is here for backward-compatibility from before we required + // C++-11. + template + class to_u + { + public: + typedef typename std::make_unsigned::type type; + }; + + // Basic IntConverter class, which converts an integer from the + // From class to one of the To class if it can be done safely and + // throws a range_error otherwise. This class is specialized for + // each permutation of signed/unsigned for the From and To + // classes. + template < + typename From, + typename To, + bool From_signed = std::numeric_limits::is_signed, + bool To_signed = std::numeric_limits::is_signed> + class IntConverter + { + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both unsigned. + if (i > std::numeric_limits::max()) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both signed. + if ((i < std::numeric_limits::min()) || (i > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is signed, and To is unsigned. If i > 0, it's safe to + // convert it to the corresponding unsigned type and to + // compare with To's max. + auto ii = static_cast::type>(i); + if ((i < 0) || (ii > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is unsigned, and to is signed. Convert To's max to the + // unsigned version of To and compare i against that. + auto maxval = static_cast::type>(std::numeric_limits::max()); + if (i > maxval) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + // Specific converters. The return type of each function must match + // the second template parameter to IntConverter. + template + inline char + to_char(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned char + to_uchar(T const& i) + { + return IntConverter::convert(i); + } + + template + inline short + to_short(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned short + to_ushort(T const& i) + { + return IntConverter::convert(i); + } + + template + inline int + to_int(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned int + to_uint(T const& i) + { + return IntConverter::convert(i); + } + + template + inline size_t + to_size(T const& i) + { + return IntConverter::convert(i); + } + + template + inline qpdf_offset_t + to_offset(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long + to_long(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long + to_ulong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long long + to_longlong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long long + to_ulonglong(T const& i) + { + return IntConverter::convert(i); + } + + template + void + range_check_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::max() - cur) < delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::min() - cur) > delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check(T const& cur, T const& delta) + { + if ((delta > 0) != (cur > 0)) { + return; + } + QIntC::range_check_error(cur, delta); + } + + template + void + range_check_subtract_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::min() + delta) > cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur + << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::max() + delta) < cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check_subtract(T const& cur, T const& delta) + { + if ((delta >= 0) == (cur >= 0)) { + return; + } + QIntC::range_check_subtract_error(cur, delta); + } +}; // namespace QIntC + +#endif // QINTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDF.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDF.hh new file mode 100644 index 0000000..5f990b7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDF.hh @@ -0,0 +1,804 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_HH +#define QPDF_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFLogger; + +class QPDF +{ + public: + // Get the current version of the QPDF software. See also qpdf/DLL.h + QPDF_DLL + static std::string const& QPDFVersion(); + + QPDF_DLL + QPDF(); + QPDF_DLL + ~QPDF(); + + QPDF_DLL + static std::shared_ptr create(); + + // Associate a file with a QPDF object and do initial parsing of the file. PDF objects are not + // read until they are needed. A QPDF object may be associated with only one file in its + // lifetime. This method must be called before any methods that potentially ask for information + // about the PDF file are called. Prior to calling this, the only methods that are allowed are + // those that set parameters. If the input file is not encrypted, either a null password or an + // empty password can be used. If the file is encrypted, either the user password or the owner + // password may be supplied. The method setPasswordIsHexKey may be called prior to calling this + // method or any of the other process methods to force the password to be interpreted as a raw + // encryption key. See comments on setPasswordIsHexKey for more information. + QPDF_DLL + void processFile(char const* filename, char const* password = nullptr); + + // Parse a PDF from a stdio FILE*. The FILE must be open in binary mode and must be seekable. + // It may be open read only. This works exactly like processFile except that the PDF file is + // read from an already opened FILE*. If close_file is true, the file will be closed at the + // end. Otherwise, the caller is responsible for closing the file. + QPDF_DLL + void processFile( + char const* description, FILE* file, bool close_file, char const* password = nullptr); + + // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except + // that the PDF file is in memory instead of on disk. The description appears in any warning or + // error message in place of the file name. The buffer is owned by the caller and must remain + // valid for the lifetime of the QPDF object. + QPDF_DLL + void processMemoryFile( + char const* description, char const* buf, size_t length, char const* password = nullptr); + + // Parse a PDF file loaded from a custom InputSource. If you have your own method of retrieving + // a PDF file, you can subclass InputSource and use this method. + QPDF_DLL + void processInputSource(std::shared_ptr, char const* password = nullptr); + + // Create a PDF from an input source that contains JSON as written by writeJSON (or qpdf + // --json-output, version 2 or higher). The JSON must be a complete representation of a PDF. See + // "qpdf JSON" in the manual for details. The input JSON may be arbitrarily large. QPDF does not + // load stream data into memory for more than one stream at a time, even if the stream data is + // specified inline. + QPDF_DLL + void createFromJSON(std::string const& json_file); + QPDF_DLL + void createFromJSON(std::shared_ptr); + + // Update a PDF from an input source that contains JSON in the same format as is written by + // writeJSON (or qpdf --json-output, version 2 or higher). Objects in the PDF and not in the + // JSON are not modified. See "qpdf JSON" in the manual for details. As with createFromJSON, the + // input JSON may be arbitrarily large. + QPDF_DLL + void updateFromJSON(std::string const& json_file); + QPDF_DLL + void updateFromJSON(std::shared_ptr); + + // Write qpdf JSON format to the pipeline "p". The only supported version is 2. The finish() + // method is not called on the pipeline. + // + // The decode_level parameter controls which streams are uncompressed in the JSON. Use + // qpdf_dl_none to preserve all stream data exactly as it appears in the input. The possible + // values for json_stream_data can be found in qpdf/Constants.h and correspond to the + // --json-stream-data command-line argument. If json_stream_data is qpdf_sj_file, file_prefix + // must be specified. Each stream will be written to a file whose path is constructed by + // appending "-nnn" to file_prefix, where "nnn" is the object number (not zero-filled). If + // wanted_objects is empty, write all objects. Otherwise, write only objects whose keys are in + // wanted_objects. Keys may be either "trailer" or of the form "obj:n n R". Invalid keys are + // ignored. This corresponds to the --json-object command-line argument. + // + // QPDF is efficient with regard to memory when writing, allowing you to write arbitrarily large + // PDF files to a pipeline. You can use a pipeline like Pl_Buffer or Pl_String to capture the + // JSON output in memory, but do so with caution as this will allocate enough memory to hold the + // entire PDF file. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // This version of writeJSON enables writing only the "qpdf" key of an in-progress dictionary. + // If the value of "complete" is true, a complete JSON object containing only the "qpdf" key is + // written to the pipeline. If the value of "complete" is false, the "qpdf" key and its value + // are written to the pipeline assuming that a dictionary is already open. The parameter + // first_key indicates whether this is the first key in an in-progress dictionary. It will be + // set to false by writeJSON. The "qpdf" key and value are written as if at depth 1 in a + // prettified JSON output. Remaining arguments are the same as the above version. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + bool complete, + bool& first_key, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // Close or otherwise release the input source. Once this has been called, no other methods of + // qpdf can be called safely except for getWarnings and anyWarnings(). After this has been + // called, it is safe to perform operations on the input file such as deleting or renaming it. + QPDF_DLL + void closeInputSource(); + + // For certain forensic or investigatory purposes, it may sometimes be useful to specify the + // encryption key directly, even though regular PDF applications do not provide a way to do + // this. Calling setPasswordIsHexKey(true) before calling any of the process methods will bypass + // the normal encryption key computation or recovery mechanisms and interpret the bytes in the + // password as a hex-encoded encryption key. Note that we hex-encode the key because it may + // contain null bytes and therefore can't be represented in a char const*. + QPDF_DLL + void setPasswordIsHexKey(bool); + + // Create a QPDF object for an empty PDF. This PDF has no pages or objects other than a minimal + // trailer, a document catalog, and a /Pages tree containing zero pages. Pages and other + // objects can be added to the file in the normal way, and the trailer and document catalog can + // be mutated. Calling this method is equivalent to calling processFile on an equivalent PDF + // file. See the pdf-create.cc example for a demonstration of how to use this method to create + // a PDF file from scratch. + QPDF_DLL + void emptyPDF(); + + // From 10.1: register a new filter implementation for a specific stream filter. You can add + // your own implementations for new filter types or override existing ones provided by the + // library. Registered stream filters are used for decoding only as you can override encoding + // with stream data providers. For example, you could use this method to add support for one of + // the other filter types by using additional third-party libraries that qpdf does not presently + // use. The standard filters are implemented using QPDFStreamFilter classes. + QPDF_DLL + static void registerStreamFilter( + std::string const& filter_name, std::function()> factory); + + // Parameter settings + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // Note that no normal QPDF operations generate output to standard output, so for applications + // that just wish to avoid creating output for warnings and don't call any check functions, + // calling setSuppressWarnings(true) is sufficient. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // If true, ignore any cross-reference streams in a hybrid file (one that contains both + // cross-reference streams and cross-reference tables). This can be useful for testing to + // ensure that a hybrid file would work with an older reader. + QPDF_DLL + void setIgnoreXRefStreams(bool); + + // By default, any warnings are issued to std::cerr or the error stream specified in a call to + // setOutputStreams as they are encountered. If this method is called with a true value, + // reporting of warnings is suppressed. You may still retrieve warnings by calling getWarnings. + QPDF_DLL + void setSuppressWarnings(bool); + + // Set the maximum number of warnings. A QPDFExc is thrown if the limit is exceeded. + QPDF_DLL + void setMaxWarnings(size_t); + + // By default, QPDF will try to recover if it finds certain types of errors in PDF files. If + // turned off, it will throw an exception on the first such problem it finds without attempting + // recovery. + QPDF_DLL + void setAttemptRecovery(bool); + + // Tell other QPDF objects that streams copied from this QPDF need to be fully copied when + // copyForeignObject is called on them. Calling setIgnoreXRefStreams(true) on a QPDF object + // makes it possible for the object and its input source to disappear before streams copied from + // it are written with the destination QPDF object. Confused? Ordinarily, if you are going to + // copy objects from a source QPDF object to a destination QPDF object using copyForeignObject + // or addPage, the source object's input source must stick around until after the destination + // PDF is written. If you call this method on the source QPDF object, it sends a signal to the + // destination object that it must fully copy the stream data when copyForeignObject. It will do + // this by making a copy in RAM. Ordinarily the stream data is copied lazily to avoid + // unnecessary duplication of the stream data. Note that the stream data is copied into RAM only + // once regardless of how many objects the stream is copied into. The result is that, if you + // called setImmediateCopyFrom(true) on a given QPDF object prior to copying any of its streams, + // you do not need to keep it or its input source around after copying its objects to another + // QPDF. This is true even if the source streams use StreamDataProvider. Note that this method + // is called on the QPDF object you are copying FROM, not the one you are copying to. The + // reasoning for this is that there's no reason a given QPDF may not get objects copied to it + // from a variety of other objects, some transient and some not. Since what's relevant is + // whether the source QPDF is transient, the method must be called on the source QPDF, not the + // destination one. This method will make a copy of the stream in RAM, so be sure you have + // enough memory to simultaneously hold all the streams you're copying. + QPDF_DLL + void setImmediateCopyFrom(bool); + + // Other public methods + + // Return the list of warnings that have been issued so far and clear the list. This method may + // be called even if processFile throws an exception. Note that if setSuppressWarnings was not + // called or was called with a false value, any warnings retrieved here will have already been + // output. + QPDF_DLL + std::vector getWarnings(); + + // Indicate whether any warnings have been issued so far. Does not clear the list of warnings. + QPDF_DLL + bool anyWarnings() const; + + // Indicate the number of warnings that have been issued since the last call to getWarnings. + // Does not clear the list of warnings. + QPDF_DLL + size_t numWarnings() const; + + // Return an application-scoped unique ID for this QPDF object. This is not a globally unique + // ID. It is constructed using a timestamp and a random number and is intended to be unique + // among QPDF objects that are created by a single run of an application. While it's very likely + // that these are actually globally unique, it is not recommended to use them for long-term + // purposes. + QPDF_DLL + unsigned long long getUniqueId() const; + + // Issue a warning on behalf of this QPDF object. It will be emitted with other warnings, + // following warning suppression rules, and it will be available with getWarnings(). + QPDF_DLL + void warn(QPDFExc const& e); + // Same as above but creates the QPDFExc object using the arguments passed to warn. The filename + // argument to QPDFExc is omitted. This method uses the filename associated with the QPDF + // object. + QPDF_DLL + void warn( + qpdf_error_code_e error_code, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // Return the filename associated with the QPDF object. + QPDF_DLL + std::string getFilename() const; + // Return PDF Version and extension level together as a PDFVersion object + QPDF_DLL + PDFVersion getVersionAsPDFVersion(); + // Return just the PDF version from the file + QPDF_DLL + std::string getPDFVersion() const; + QPDF_DLL + int getExtensionLevel(); + QPDF_DLL + QPDFObjectHandle getTrailer(); + QPDF_DLL + QPDFObjectHandle getRoot(); + QPDF_DLL + std::map getXRefTable(); + + // Public factory methods + + // Create a new stream. A subsequent call must be made to replaceStreamData() to provide data + // for the stream. The stream's dictionary may be retrieved by calling getDict(), and the + // resulting dictionary may be modified. Alternatively, you can create a new dictionary and + // call replaceDict to install it. + QPDF_DLL + QPDFObjectHandle newStream(); + + // Create a new stream. Use the given buffer as the stream data. The stream dictionary's + // /Length key will automatically be set to the size of the data buffer. If additional keys are + // required, the stream's dictionary may be retrieved by calling getDict(), and the resulting + // dictionary may be modified. This method is just a convenient wrapper around the newStream() + // and replaceStreamData(). It is a convenience methods for streams that require no parameters + // beyond the stream length. Note that you don't have to deal with compression yourself if you + // use QPDFWriter. By default, QPDFWriter will automatically compress uncompressed stream data. + // Example programs are provided that illustrate this. + QPDF_DLL + QPDFObjectHandle newStream(std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + QPDF_DLL + QPDFObjectHandle newStream(std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. + QPDF_DLL + QPDFObjectHandle newReserved(); + QPDF_DLL + QPDFObjectHandle newIndirectNull(); + + // Install this object handle as an indirect object and return an indirect reference to it. + QPDF_DLL + QPDFObjectHandle makeIndirectObject(QPDFObjectHandle); + + // Retrieve an object by object ID and generation. Returns an indirect reference to it. The + // getObject() methods were added for qpdf 11. + QPDF_DLL + QPDFObjectHandle getObject(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObject(int objid, int generation); + // These are older methods, but there is no intention to deprecate + // them. + QPDF_DLL + QPDFObjectHandle getObjectByObjGen(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObjectByID(int objid, int generation); + + // Replace the object with the given object id with the given object. The object handle passed + // in must be a direct object, though it may contain references to other indirect objects within + // it. Prior to qpdf 10.2.1, after calling this method, existing QPDFObjectHandle instances that + // pointed to the original object still pointed to the original object, resulting in confusing + // and incorrect behavior. This was fixed in 10.2.1, so existing QPDFObjectHandle objects will + // start pointing to the newly replaced object. Note that replacing an object with + // QPDFObjectHandle::newNull() effectively removes the object from the file since a non-existent + // object is treated as a null object. To replace a reserved object, call replaceReserved + // instead. + QPDF_DLL + void replaceObject(QPDFObjGen og, QPDFObjectHandle); + QPDF_DLL + void replaceObject(int objid, int generation, QPDFObjectHandle); + + // Swap two objects given by ID. Prior to qpdf 10.2.1, existing QPDFObjectHandle instances that + // reference them objects not notice the swap, but this was fixed in 10.2.1. + QPDF_DLL + void swapObjects(QPDFObjGen og1, QPDFObjGen og2); + QPDF_DLL + void swapObjects(int objid1, int generation1, int objid2, int generation2); + + // Replace a reserved object. This is a wrapper around replaceObject but it guarantees that the + // underlying object is a reserved object or a null object. After this call, reserved will + // be a reference to replacement. + QPDF_DLL + void replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement); + + // Copy an object from another QPDF to this one. Starting with qpdf version 8.3.0, it is no + // longer necessary to keep the original QPDF around after the call to copyForeignObject as long + // as the source of any copied stream data is still available. Usually this means you just have + // to keep the input file around, not the QPDF object. The exception to this is if you copy a + // stream that gets its data from a QPDFObjectHandle::StreamDataProvider. In this case only, the + // original stream's QPDF object must stick around because the QPDF object is itself the source + // of the original stream data. For a more in-depth discussion, please see the TODO file. + // Starting in 8.4.0, you can call setImmediateCopyFrom(true) on the SOURCE QPDF object (the one + // you're copying FROM). If you do this prior to copying any of its objects, then neither the + // source QPDF object nor its input source needs to stick around at all regardless of the + // source. The cost is that the stream data is copied into RAM at the time copyForeignObject is + // called. See setImmediateCopyFrom for more information. + // + // The return value of this method is an indirect reference to the copied object in this file. + // This method is intended to be used to copy non-page objects. To copy page objects, pass the + // foreign page object directly to addPage (or addPageAt). If you copy objects that contain + // references to pages, you should copy the pages first using addPage(At). Otherwise references + // to the pages that have not been copied will be replaced with nulls. It is possible to use + // copyForeignObject on page objects if you are not going to use them as pages. Doing so copies + // the object normally but does not update the page structure. For example, it is a valid use + // case to use copyForeignObject for a page that you are going to turn into a form XObject, + // though you can also use QPDFPageObjectHelper::getFormXObjectForPage for that purpose. + // + // When copying objects with this method, object structure will be preserved, so all indirectly + // referenced indirect objects will be copied as well. This includes any circular references + // that may exist. The QPDF object keeps a record of what has already been copied, so shared + // objects will not be copied multiple times. This also means that if you mutate an object that + // has already been copied and try to copy it again, it won't work since the modified object + // will not be recopied. Therefore, you should do all mutation on the original file that you + // are going to do before you start copying its objects to a new file. + QPDF_DLL + QPDFObjectHandle copyForeignObject(QPDFObjectHandle foreign); + + // Encryption support + + enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes, e_aesv3 }; + + // To be removed from the public API in qpdf 13. See + // . + class EncryptionData + { + public: + // This class holds data read from the encryption dictionary. + EncryptionData( + int V, + int R, + int Length_bytes, + int P, + std::string const& O, + std::string const& U, + std::string const& OE, + std::string const& UE, + std::string const& Perms, + std::string const& id1, + bool encrypt_metadata) : + V(V), + R(R), + Length_bytes(Length_bytes), + P(P), + O(O), + U(U), + OE(OE), + UE(UE), + Perms(Perms), + id1(id1), + encrypt_metadata(encrypt_metadata) + { + } + + int getV() const; + int getR() const; + int getLengthBytes() const; + int getP() const; + std::string const& getO() const; + std::string const& getU() const; + std::string const& getOE() const; + std::string const& getUE() const; + std::string const& getPerms() const; + std::string const& getId1() const; + bool getEncryptMetadata() const; + + void setO(std::string const&); + void setU(std::string const&); + void setV5EncryptionParameters( + std::string const& O, + std::string const& OE, + std::string const& U, + std::string const& UE, + std::string const& Perms); + + private: + EncryptionData(EncryptionData const&) = delete; + EncryptionData& operator=(EncryptionData const&) = delete; + + int V; + int R; + int Length_bytes; + int P; + std::string O; + std::string U; + std::string OE; + std::string UE; + std::string Perms; + std::string id1; + bool encrypt_metadata; + }; + QPDF_DLL + bool isEncrypted() const; + + QPDF_DLL + bool isEncrypted(int& R, int& P); + + QPDF_DLL + bool isEncrypted( + int& R, + int& P, + int& V, + encryption_method_e& stream_method, + encryption_method_e& string_method, + encryption_method_e& file_method); + + QPDF_DLL + bool ownerPasswordMatched() const; + + QPDF_DLL + bool userPasswordMatched() const; + + // Encryption permissions -- not enforced by QPDF + QPDF_DLL + bool allowAccessibility(); + QPDF_DLL + bool allowExtractAll(); + QPDF_DLL + bool allowPrintLowRes(); + QPDF_DLL + bool allowPrintHighRes(); + QPDF_DLL + bool allowModifyAssembly(); + QPDF_DLL + bool allowModifyForm(); + QPDF_DLL + bool allowModifyAnnotation(); + QPDF_DLL + bool allowModifyOther(); + QPDF_DLL + bool allowModifyAll(); + + // Helper function to trim padding from user password. Calling trim_user_password on the result + // of getPaddedUserPassword gives getTrimmedUserPassword's result. + QPDF_DLL + static void trim_user_password(std::string& user_password); + QPDF_DLL + static std::string compute_data_key( + std::string const& encryption_key, + int objid, + int generation, + bool use_aes, + int encryption_V, + int encryption_R); + + // To be removed in qpdf 13. See . + [[deprecated("to be removed in qpdf 13")]] + QPDF_DLL static std::string + compute_encryption_key(std::string const& password, EncryptionData const& data); + + QPDF_DLL + static void compute_encryption_O_U( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& O, + std::string& U); + QPDF_DLL + static void compute_encryption_parameters_V5( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& encryption_key, + std::string& O, + std::string& U, + std::string& OE, + std::string& UE, + std::string& Perms); + // Return the full user password as stored in the PDF file. For files encrypted with 40-bit or + // 128-bit keys, the user password can be recovered when the file is opened using the owner + // password. This is not possible with newer encryption formats. If you are attempting to + // recover the user password in a user-presentable form, call getTrimmedUserPassword() instead. + QPDF_DLL + std::string const& getPaddedUserPassword() const; + // Return human-readable form of user password subject to same limitations as + // getPaddedUserPassword(). + QPDF_DLL + std::string getTrimmedUserPassword() const; + // Return the previously computed or retrieved encryption key for this file + QPDF_DLL + std::string getEncryptionKey() const; + // Remove security restrictions associated with digitally signed files. From qpdf 11.7.0, this + // is called by QPDFAcroFormDocumentHelper::disableDigitalSignatures and is more useful when + // called from there than when just called by itself. + QPDF_DLL + void removeSecurityRestrictions(); + + // Linearization support + + // Returns true iff the file starts with a linearization parameter dictionary. Does no + // additional validation. + QPDF_DLL + bool isLinearized(); + + // Performs various sanity checks on a linearized file. Return true if no errors or warnings. + // Otherwise, return false and output errors and warnings to the default output stream + // (std::cout or whatever is configured in the logger). It is recommended for linearization + // errors to be treated as warnings. + QPDF_DLL + bool checkLinearization(); + + // Calls checkLinearization() and, if possible, prints normalized contents of some of the hints + // tables to the default output stream. Normalization includes adding min values to delta values + // and adjusting offsets based on the location and size of the primary hint stream. + QPDF_DLL + void showLinearizationData(); + + // Shows the contents of the cross-reference table + QPDF_DLL + void showXRefTable(); + + // Starting from qpdf 11.0 user code should not need to call this method. Before 11.0 this + // method was used to detect all indirect references to objects that don't exist and resolve + // them by replacing them with null, which is how the PDF spec says to interpret such dangling + // references. This method is called automatically when you try to add any new objects, if you + // call getAllObjects, and before a file is written. The qpdf object caches whether it has run + // this to avoid running it multiple times. Before 11.2.1 you could pass true to force it to run + // again if you had explicitly added new objects that may have additional dangling references. + QPDF_DLL + void fixDanglingReferences(bool force = false); + + // Return the approximate number of indirect objects. It is/ approximate because not all objects + // in the file are preserved in all cases, and gaps in object numbering are not preserved. + QPDF_DLL + size_t getObjectCount(); + + // Returns a list of indirect objects for every object in the xref table. Useful for discovering + // objects that are not otherwise referenced. + QPDF_DLL + std::vector getAllObjects(); + + // Optimization support -- see doc/optimization. Implemented in QPDF_optimization.cc + + // The object_stream_data map maps from a "compressed" object to the object stream that contains + // it. This enables optimize to populate the object <-> user maps with only uncompressed + // objects. If allow_changes is false, an exception will be thrown if any changes are made + // during the optimization process. This is available so that the test suite can make sure that + // a linearized file is already optimized. When called in this way, optimize() still populates + // the object <-> user maps. The optional skip_stream_parameters parameter, if present, is + // called for each stream object. The function should return 2 if optimization should discard + // /Length, /Filter, and /DecodeParms; 1 if it should discard /Length, and 0 if it should + // preserve all keys. This is used by QPDFWriter to avoid creation of dangling objects for + // stream dictionary keys it will be regenerating. + [[deprecated("Unused - see release notes for qpdf 12.1.0")]] QPDF_DLL void optimize( + std::map const& object_stream_data, + bool allow_changes = true, + std::function skip_stream_parameters = nullptr); + + // Traverse page tree return all /Page objects. It also detects and resolves cases in which the + // same /Page object is duplicated. For efficiency, this method returns a const reference to an + // internal vector of pages. Calls to addPage, addPageAt, and removePage safely update this, but + // direct manipulation of the pages tree or pushing inheritable objects to the page level may + // invalidate it. See comments for updateAllPagesCache() for additional notes. Newer code should + // use QPDFPageDocumentHelper::getAllPages instead. The decision to expose this internal cache + // was arguably incorrect, but it is being left here for compatibility. It is, however, + // completely safe to use this for files that you are not modifying. + QPDF_DLL + std::vector const& getAllPages(); + + QPDF_DLL + bool everCalledGetAllPages() const; + QPDF_DLL + bool everPushedInheritedAttributesToPages() const; + + // These methods, given a page object or its object/generation number, returns the 0-based index + // into the array returned by getAllPages() for that page. An exception is thrown if the page is + // not found. + QPDF_DLL + int findPage(QPDFObjGen og); + QPDF_DLL + int findPage(QPDFObjectHandle& page); + + // This method synchronizes QPDF's cache of the page structure with the actual /Pages tree. If + // you restrict changes to the /Pages tree, including addition, removal, or replacement of pages + // or changes to any /Pages objects, to calls to these page handling APIs, you never need to + // call this method. If you modify /Pages structures directly, you must call this method + // afterwards. This method updates the internal list of pages, so after calling this method, + // any previous references returned by getAllPages() will be valid again. It also resets any + // state about having pushed inherited attributes in /Pages objects down to the pages, so if you + // add any inheritable attributes to a /Pages object, you should also call this method. + QPDF_DLL + void updateAllPagesCache(); + + // Legacy handling API. These methods are not going anywhere, and you should feel free to + // continue using them if it simplifies your code. Newer code should make use of + // QPDFPageDocumentHelper instead as future page handling methods will be added there. The + // functionality and specification of these legacy methods is identical to the identically named + // methods there, except that these versions use QPDFObjectHandle instead of + // QPDFPageObjectHelper, so please see comments in that file for descriptions. There are + // subtleties you need to know about, so please look at the comments there. + QPDF_DLL + void pushInheritedAttributesToPage(); + QPDF_DLL + void addPage(QPDFObjectHandle newpage, bool first); + QPDF_DLL + void addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage); + QPDF_DLL + void removePage(QPDFObjectHandle page); + // End legacy page helpers + + // End of the public API. The following classes and methods are for qpdf internal use only. + + class Doc; + + inline Doc& doc(); + + // For testing only -- do not add to DLL + static bool test_json_validators(); + + private: + // It has never been safe to copy QPDF objects as there is code in the library that assumes + // there are no copies of a QPDF object. Copying QPDF objects was not prevented by the API until + // qpdf 11. If you have been copying QPDF objects, use std::shared_ptr instead. From qpdf + // 11, you can use QPDF::create to create them. + QPDF(QPDF const&) = delete; + QPDF& operator=(QPDF const&) = delete; + + static std::string const qpdf_version; + + class ObjCache; + class EncryptionParameters; + class StringDecrypter; + class ResolveRecorder; + class JSONReactor; + + void removeObject(QPDFObjGen og); + + // Calls finish() on the pipeline when done but does not delete it + bool pipeStreamData( + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + static bool pipeStreamData( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + + // methods to support encryption -- implemented in QPDF_encryption.cc + void initializeEncryption(); + static std::string + getKeyForObject(std::shared_ptr encp, QPDFObjGen og, bool use_aes); + void decryptString(std::string&, QPDFObjGen og); + static void decryptStream( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + Pipeline*& pipeline, + QPDFObjGen og, + QPDFObjectHandle& stream_dict, + bool is_root_metadata, + std::unique_ptr& heap); + + // JSON import + void importJSON(std::shared_ptr, bool must_be_complete); + + class Members; + + // Keep all member variables inside the Members object, which we dynamically allocate. This + // makes it possible to add new private members without breaking binary compatibility. + std::unique_ptr m; +}; + +#endif // QPDF_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFAcroFormDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFAcroFormDocumentHelper.hh new file mode 100644 index 0000000..935e161 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFAcroFormDocumentHelper.hh @@ -0,0 +1,234 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFACROFORMDOCUMENTHELPER_HH +#define QPDFACROFORMDOCUMENTHELPER_HH + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +// This document helper is intended to help with operations on interactive forms. Here are the key +// things to know: + +// * The PDF specification talks about interactive forms and also about form XObjects. While form +// XObjects appear in parts of interactive forms, this class is concerned about interactive forms, +// not form XObjects. +// +// * Interactive forms are discussed in the PDF Specification (ISO PDF 32000-1:2008) section 12.7. +// Also relevant is the section about Widget annotations. Annotations are discussed in section +// 12.5 with annotation dictionaries discussed in 12.5.1. Widget annotations are discussed +// specifically in section 12.5.6.19. +// +// * What you need to know about the structure of interactive forms in PDF files: +// +// - The document catalog contains the key "/AcroForm" which contains a list of fields. Fields are +// represented as a tree structure much like pages. Nodes in the fields tree may contain other +// fields. Fields may inherit values of many of their attributes from ancestors in the tree. +// +// - Fields may also have children that are widget annotations. As a special case, and a cause of +// considerable confusion, if a field has a single annotation as a child, the annotation +// dictionary may be merged with the field dictionary. In that case, the field and the +// annotation are in the same object. Note that, while field dictionary attributes are +// inherited, annotation dictionary attributes are not. +// +// - A page dictionary contains a key called "/Annots" which contains a simple list of +// annotations. For any given annotation of subtype "/Widget", you should encounter that +// annotation in the "/Annots" dictionary of a page, and you should also be able to reach it by +// traversing through the "/AcroForm" dictionary from the document catalog. In the simplest case +// (and also a very common case), a form field's widget annotation will be merged with the field +// object, and the object will appear directly both under "/Annots" in the page dictionary and +// under "/Fields" in the "/AcroForm" dictionary. In a more complex case, you may have to trace +// through various "/Kids" elements in the "/AcroForm" field entry until you find the annotation +// dictionary. +class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFAcroFormDocumentHelper& get(QPDF& qpdf); + + // Re-validate the AcroForm structure. This is useful if you have modified the structure of the + // AcroForm dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFAcroFormDocumentHelper(QPDF&); + + ~QPDFAcroFormDocumentHelper() override = default; + + // This class lazily creates an internal cache of the mapping among form fields, annotations, + // and pages. Methods within this class preserve the validity of this cache. However, if you + // modify pages' annotation dictionaries, the document's /AcroForm dictionary, or any form + // fields manually in a way that alters the association between forms, fields, annotations, and + // pages, it may cause this cache to become invalid. This method marks the cache invalid and + // forces it to be regenerated the next time it is needed. + QPDF_DLL + void invalidateCache(); + + QPDF_DLL + bool hasAcroForm(); + + // Add a form field, initializing the document's AcroForm dictionary if needed, updating the + // cache if necessary. Note that you are adding fields that are copies of other fields, this + // method may result in multiple fields existing with the same qualified name, which can have + // unexpected side effects. In that case, you should use addAndRenameFormFields() instead. + QPDF_DLL + void addFormField(QPDFFormFieldObjectHelper); + + // Add a collection of form fields making sure that their fully qualified names don't conflict + // with already present form fields. Fields within the collection of new fields that have the + // same name as each other will continue to do so. + QPDF_DLL + void addAndRenameFormFields(std::vector fields); + + // Remove fields from the fields array + QPDF_DLL + void removeFormFields(std::set const&); + + // Set the name of a field, updating internal records of field names. Name should be UTF-8 + // encoded. + QPDF_DLL + void setFormFieldName(QPDFFormFieldObjectHelper, std::string const& name); + + // Return a vector of all terminal fields in a document. Terminal fields are fields that have no + // children that are also fields. Terminal fields may still have children that are annotations. + // Intermediate nodes in the fields tree are not included in this list, but you can still reach + // them through the getParent method of the field object helper. + QPDF_DLL + std::vector getFormFields(); + + // Return all the form fields that have the given fully-qualified name and also have an explicit + // "/T" attribute. For this information to be accurate, any changes to field names must be done + // through setFormFieldName() above. + QPDF_DLL + std::set getFieldsWithQualifiedName(std::string const& name); + + // Return the annotations associated with a terminal field. Note that in the case of a field + // having a single annotation, the underlying object will typically be the same as the + // underlying object for the field. + QPDF_DLL + std::vector getAnnotationsForField(QPDFFormFieldObjectHelper); + + // Return annotations of subtype /Widget for a page. + QPDF_DLL + std::vector getWidgetAnnotationsForPage(QPDFPageObjectHelper); + + // Return top-level form fields for a page. + QPDF_DLL + std::vector getFormFieldsForPage(QPDFPageObjectHelper); + + // Return the terminal field that is associated with this annotation. If the annotation + // dictionary is merged with the field dictionary, the underlying object will be the same, but + // this is not always the case. Note that if you call this method with an annotation that is not + // a widget annotation, there will not be an associated field, and this method will return a + // helper associated with a null object (isNull() == true). + QPDF_DLL + QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper); + + // Return the current value of /NeedAppearances. If /NeedAppearances is missing, return false as + // that is how PDF viewers are supposed to interpret it. + QPDF_DLL + bool getNeedAppearances(); + + // Indicate whether appearance streams must be regenerated. If you modify a field value, you + // should call setNeedAppearances(true) unless you also generate an appearance stream for the + // corresponding annotation at the same time. If you generate appearance streams for all fields, + // you can call setNeedAppearances(false). If you use QPDFFormFieldObjectHelper::setV, it will + // automatically call this method unless you tell it not to. + QPDF_DLL + void setNeedAppearances(bool); + + // If /NeedAppearances is false, do nothing. Otherwise generate appearance streams for all + // widget annotations that need them. See comments in QPDFFormFieldObjectHelper.hh for + // generateAppearance for limitations. For checkbox and radio button fields, this code ensures + // that appearance state is consistent with the field's value and uses any pre-existing + // appearance streams. + QPDF_DLL + void generateAppearancesIfNeeded(); + + // Disable Digital Signature Fields. Remove all digital signature fields from the document, + // leaving any annotation showing the content of the field intact. This also calls + // QPDF::removeSecurityRestrictions. + QPDF_DLL + void disableDigitalSignatures(); + + // Note: this method works on all annotations, not just ones with associated fields. For each + // annotation in old_annots, apply the given transformation matrix to create a new annotation. + // New annotations are appended to new_annots. If the annotation is associated with a form + // field, a new form field is created that points to the new annotation and is appended to + // new_fields, and the old field is added to old_fields. + // + // old_annots may belong to a different QPDF object. In that case, you should pass in from_qpdf, + // and copyForeignObject will be called automatically. If this is the case, for efficiency, you + // may pass in a QPDFAcroFormDocumentHelper for the other file to avoid the expensive process of + // creating one for each call to transformAnnotations. New fields and annotations are not added + // to the document or pages. You have to do that yourself after calling transformAnnotations. If + // this operation will leave orphaned fields behind, such as if you are replacing the old + // annotations with the new ones on the same page and the fields and annotations are not shared, + // you will also need to remove the old fields to prevent them from hanging around unreferenced. + QPDF_DLL + void transformAnnotations( + QPDFObjectHandle old_annots, + std::vector& new_annots, + std::vector& new_fields, + std::set& old_fields, + QPDFMatrix const& cm, + QPDF* from_qpdf = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + // Copy form fields and annotations from one page to another, allowing the from page to be in a + // different QPDF or in the same QPDF. This would typically be called after calling addPage to + // add field/annotation awareness. When just copying the page by itself, annotations end up + // being shared, and fields end up being omitted because there is no reference to the field from + // the page. This method ensures that each separate copy of a page has private annotations and + // that fields and annotations are properly updated to resolve conflicts that may occur from + // common resource and field names across documents. It is basically a wrapper around + // transformAnnotations that handles updating the receiving page. If new_fields is non-null, any + // newly created fields are added to it. + QPDF_DLL + void fixCopiedAnnotations( + QPDFObjectHandle to_page, + QPDFObjectHandle from_page, + QPDFAcroFormDocumentHelper& from_afdh, + std::set* new_fields = nullptr); + + private: + friend class QPDF::Doc; + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFACROFORMDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFAnnotationObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFAnnotationObjectHelper.hh new file mode 100644 index 0000000..1f50d80 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFAnnotationObjectHelper.hh @@ -0,0 +1,105 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFANNOTATIONOBJECTHELPER_HH +#define QPDFANNOTATIONOBJECTHELPER_HH + +#include +#include + +#include + +class QPDFAnnotationObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFAnnotationObjectHelper(QPDFObjectHandle); + + ~QPDFAnnotationObjectHelper() override = default; + + // This class provides helper methods for annotations. More functionality will likely be added + // in the future. + + // Some functionality for annotations is also implemented in QPDFAcroFormDocumentHelper and + // QPDFFormFieldObjectHelper. In some cases, functions defined there work for other annotations + // besides widget annotations, but they are implemented with form fields so that they can + // properly handle form fields when needed. + + // Return the subtype of the annotation as a string (e.g. "/Widget"). Returns an empty string + // if the subtype (which is required by the spec) is missing. + QPDF_DLL + std::string getSubtype(); + + QPDF_DLL + QPDFObjectHandle::Rectangle getRect(); + + QPDF_DLL + QPDFObjectHandle getAppearanceDictionary(); + + // Return the appearance state as given in "/AS", or an empty string if none is given. + QPDF_DLL + std::string getAppearanceState(); + + // Return flags from "/F". The value is a logical or of pdf_annotation_flag_e as defined in + // qpdf/Constants.h. + QPDF_DLL + int getFlags(); + + // Return a specific stream. "which" may be one of "/N", "/R", or "/D" to indicate the normal, + // rollover, or down appearance stream. (Any value may be passed to "which"; if an appearance + // stream of that name exists, it will be returned.) If the value associated with "which" in the + // appearance dictionary is a subdictionary, an appearance state may be specified to select + // which appearance stream is desired. If not specified, the appearance state in "/AS" will + // used. + QPDF_DLL + QPDFObjectHandle getAppearanceStream(std::string const& which, std::string const& state = ""); + + // Generate text suitable for addition to the containing page's content stream that draws this + // annotation's appearance stream as a form XObject. The value "name" is the resource name that + // will be used to refer to the form xobject. The value "rotate" should be set to the page's + // /Rotate value or 0 if none. The values of required_flags and forbidden_flags are constructed + // by logically "or"ing annotation flags of type pdf_annotation_flag_e defined in + // qpdf/Constants.h. Content will be returned only if all required_flags are set and no + // forbidden_flags are set. For example, including an_no_view in forbidden_flags could be useful + // for creating an on-screen view, and including an_print to required_flags could be useful if + // preparing to print. + QPDF_DLL + std::string getPageContentForAppearance( + std::string const& name, + int rotate, + int required_flags = 0, + int forbidden_flags = an_invisible | an_hidden); + + private: + class Members + { + friend class QPDFAnnotationObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFANNOTATIONOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFCryptoImpl.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFCryptoImpl.hh new file mode 100644 index 0000000..34bbd98 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFCryptoImpl.hh @@ -0,0 +1,82 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFCRYPTOIMPL_HH +#define QPDFCRYPTOIMPL_HH + +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. +// Most users won't need to know or care about this class, but you can +// use it if you want to supply your own crypto implementation. To do +// so, provide an implementation of QPDFCryptoImpl, ensure that you +// register it by calling QPDFCryptoProvider::registerImpl, and make +// it the default by calling QPDFCryptoProvider::setDefaultProvider. +class QPDF_DLL_CLASS QPDFCryptoImpl +{ + public: + QPDFCryptoImpl() = default; + + virtual ~QPDFCryptoImpl() = default; + + // Random Number Generation + + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + // Hashing + + typedef unsigned char MD5_Digest[16]; + virtual void MD5_init() = 0; + virtual void MD5_update(unsigned char const* data, size_t len) = 0; + virtual void MD5_finalize() = 0; + virtual void MD5_digest(MD5_Digest) = 0; + + virtual void SHA2_init(int bits) = 0; + virtual void SHA2_update(unsigned char const* data, size_t len) = 0; + virtual void SHA2_finalize() = 0; + virtual std::string SHA2_digest() = 0; + + // Encryption/Decryption + + // QPDF must support RC4 to be able to work with older PDF files + // and readers. Search for RC4 in README.md + + // key_len of -1 means treat key_data as a null-terminated string + virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0; + // out_data = 0 means to encrypt/decrypt in place + virtual void + RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data = nullptr) = 0; + virtual void RC4_finalize() = 0; + + static size_t constexpr rijndael_buf_size = 16; + virtual void rijndael_init( + bool encrypt, + unsigned char const* key_data, + size_t key_len, + bool cbc_mode, + unsigned char* cbc_block) = 0; + virtual void rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0; + virtual void rijndael_finalize() = 0; +}; + +#endif // QPDFCRYPTOIMPL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFCryptoProvider.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFCryptoProvider.hh new file mode 100644 index 0000000..44d900c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFCryptoProvider.hh @@ -0,0 +1,107 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFCRYPTOPROVIDER_HH +#define QPDFCRYPTOPROVIDER_HH + +#include +#include +#include +#include +#include +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. Most users won't need to know or +// care about this class, but you can use it if you want to supply your own crypto implementation. +// See also comments in QPDFCryptoImpl.hh. +class QPDFCryptoProvider +{ + public: + // Methods for getting and registering crypto implementations. These methods are not + // thread-safe. + + // Return an instance of a crypto provider using the default implementation. + QPDF_DLL + static std::shared_ptr getImpl(); + + // Return an instance of the crypto provider registered using the given name. + QPDF_DLL + static std::shared_ptr getImpl(std::string const& name); + + typedef std::function()> provider_fn; + + // Register a crypto implementation with the given name. The provider function must return + // a shared pointer to an instance of the implementation class, which must be derived from + // QPDFCryptoImpl. + QPDF_DLL static void registerImpl(std::string const& name, provider_fn f); + + // Register the given type (T) as a crypto implementation. T must be derived from QPDFCryptoImpl + // and must have a constructor that takes no arguments. + template + static void + registerImpl(std::string const& name) + { + registerImpl(name, std::make_shared); + } + + // Set the crypto provider registered with the given name as the default crypto implementation. + QPDF_DLL + static void setDefaultProvider(std::string const& name); + + // Get the names of registered implementations + QPDF_DLL + static std::set getRegisteredImpls(); + + // Get the name of the default crypto provider + QPDF_DLL + static std::string getDefaultProvider(); + + private: + QPDFCryptoProvider(); + ~QPDFCryptoProvider() = default; + QPDFCryptoProvider(QPDFCryptoProvider const&) = delete; + QPDFCryptoProvider& operator=(QPDFCryptoProvider const&) = delete; + + static QPDFCryptoProvider& getInstance(); + + std::shared_ptr getImpl_internal(std::string const& name) const; + void registerImpl_internal(std::string const& name, provider_fn f); + void setDefaultProvider_internal(std::string const& name); + + class Members + { + friend class QPDFCryptoProvider; + + public: + Members() = default; + ~Members() = default; + + private: + Members(Members const&) = delete; + Members& operator=(Members const&) = delete; + + std::string default_provider; + std::map providers; + }; + + std::shared_ptr m; +}; + +#endif // QPDFCRYPTOPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFDocumentHelper.hh new file mode 100644 index 0000000..67d42d4 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFDocumentHelper.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFDOCUMENTHELPER_HH +#define QPDFDOCUMENTHELPER_HH + +#include +#include + +// This is a base class for QPDF Document Helper classes. Document helpers are classes that provide +// a convenient, higher-level API for accessing document-level structures within a PDF file. +// Document helpers are always initialized with a reference to a QPDF object, and the object can +// always be retrieved. The intention is that you may freely intermix use of document helpers with +// the underlying QPDF object unless there is a specific comment in a specific helper method that +// says otherwise. The pattern of using helper objects was introduced to allow creation of higher +// level helper functions without polluting the public interface of QPDF. +class QPDF_DLL_CLASS QPDFDocumentHelper +{ + public: + QPDFDocumentHelper(QPDF& qpdf) : + qpdf(qpdf) + { + } + QPDF_DLL + virtual ~QPDFDocumentHelper(); + QPDF& + getQPDF() + { + return qpdf; + } + QPDF const& + getQPDF() const + { + return qpdf; + } + + protected: + QPDF& qpdf; +}; + +#endif // QPDFDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFEFStreamObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFEFStreamObjectHelper.hh new file mode 100644 index 0000000..fec2325 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFEFStreamObjectHelper.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEFSTREAMOBJECTHELPER_HH +#define QPDFEFSTREAMOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around Embedded File Streams, which are discussed in +// section 7.11.4 of the ISO-32000 PDF specification. +class QPDFEFStreamObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFEFStreamObjectHelper(QPDFObjectHandle); + + ~QPDFEFStreamObjectHelper() override = default; + + // Date parameters are strings that conform to the PDF spec for date/time strings, which is + // "D:yyyymmddhhmmss" where is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone + // offset. Examples: "D:20210207161528-05'00'", "D:20210207211528Z". See + // QUtil::qpdf_time_to_pdf_time. + + QPDF_DLL + std::string getCreationDate(); + QPDF_DLL + std::string getModDate(); + // Get size as reported in the object; return 0 if not present. + QPDF_DLL + size_t getSize(); + // Subtype is a mime type such as "text/plain" + QPDF_DLL + std::string getSubtype(); + // Return the checksum as stored in the object as a binary string. This does not check + // consistency with the data. If not present, return an empty string. The PDF spec specifies + // this as an MD5 checksum and notes that it is not to be used for security purposes since MD5 + // is known to be insecure. + QPDF_DLL + std::string getChecksum(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // efsoh.setCreationDate(x).setModDate(y); + + // Create a new embedded file stream with the given stream data, which can be provided in any of + // several ways. To get the new object back, call getObjectHandle() on the returned object. The + // checksum and size are computed automatically and stored. Other parameters may be supplied + // using setters defined below. + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::shared_ptr data); + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::string const& data); + // The provider function must write the data to the given pipeline. The function may be called + // multiple times by the qpdf library. You can pass QUtil::file_provider(filename) as the + // provider to have the qpdf library provide the contents of filename as a binary. + QPDF_DLL + static QPDFEFStreamObjectHelper + createEFStream(QPDF& qpdf, std::function provider); + + // Setters for other parameters + QPDF_DLL + QPDFEFStreamObjectHelper& setCreationDate(std::string const&); + QPDF_DLL + QPDFEFStreamObjectHelper& setModDate(std::string const&); + + // Set subtype as a mime-type, e.g. "text/plain" or "application/pdf". + QPDF_DLL + QPDFEFStreamObjectHelper& setSubtype(std::string const&); + + private: + QPDFObjectHandle getParam(std::string const& pkey); + void setParam(std::string const& pkey, QPDFObjectHandle const&); + static QPDFEFStreamObjectHelper newFromStream(QPDFObjectHandle stream); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEFSTREAMOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh new file mode 100644 index 0000000..12174d6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh @@ -0,0 +1,90 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEMBEDDEDFILEDOCUMENTHELPER_HH +#define QPDFEMBEDDEDFILEDOCUMENTHELPER_HH + +#include + +#include +#include +#include +#include + +#include +#include + +// This class provides a higher level interface around document-level file attachments, also known +// as embedded files. These are discussed in sections 7.7.4 and 7.11 of the ISO-32000 PDF +// specification. +class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the EmbeddedFiles structure, which can be expensive. + QPDF_DLL + static QPDFEmbeddedFileDocumentHelper& get(QPDF& qpdf); + + // Re-validate the EmbeddedFiles structure. This is useful if you have modified the structure of + // the EmbeddedFiles dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFEmbeddedFileDocumentHelper(QPDF&); + + ~QPDFEmbeddedFileDocumentHelper() override = default; + + QPDF_DLL + bool hasEmbeddedFiles() const; + + QPDF_DLL + std::map> getEmbeddedFiles(); + + // If an embedded file with the given name exists, return a (shared) pointer to it. Otherwise, + // return nullptr. + QPDF_DLL + std::shared_ptr getEmbeddedFile(std::string const& name); + + // Add or replace an attachment + QPDF_DLL + void replaceEmbeddedFile(std::string const& name, QPDFFileSpecObjectHelper const&); + + // Remove an embedded file if present. Return value is true if the file was present and was + // removed. This method not only removes the embedded file from the embedded files name tree but + // also nulls out the file specification dictionary. This means that any references to this file + // from file attachment annotations will also stop working. This is the best way to make the + // attachment actually disappear from the file and not just from the list of attachments. + QPDF_DLL + bool removeEmbeddedFile(std::string const& name); + + private: + void initEmbeddedFiles(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEMBEDDEDFILEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFExc.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFExc.hh new file mode 100644 index 0000000..9038418 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFExc.hh @@ -0,0 +1,89 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEXC_HH +#define QPDFEXC_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFExc: public std::runtime_error +{ + public: + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message, + bool zero_offset_valid); + + ~QPDFExc() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. Only the error code and message are + // guaranteed to have non-zero/empty values. + + // There is no lookup code that maps numeric error codes into strings. The numeric error code + // is just another way to get at the underlying issue, but it is more programmer-friendly than + // trying to parse a string that is subject to change. + + QPDF_DLL + qpdf_error_code_e getErrorCode() const; + QPDF_DLL + std::string const& getFilename() const; + QPDF_DLL + std::string const& getObject() const; + QPDF_DLL + qpdf_offset_t getFilePosition() const; + QPDF_DLL + std::string const& getMessageDetail() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat( + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + qpdf_error_code_e error_code; + std::string filename; + std::string object; + qpdf_offset_t offset; + std::string message; +}; + +#endif // QPDFEXC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFFileSpecObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFFileSpecObjectHelper.hh new file mode 100644 index 0000000..9a00e20 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFFileSpecObjectHelper.hh @@ -0,0 +1,94 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFILESPECOBJECTHELPER_HH +#define QPDFFILESPECOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around File Specification dictionaries, which are +// discussed in section 7.11 of the ISO-32000 PDF specification. +class QPDFFileSpecObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFileSpecObjectHelper(QPDFObjectHandle); + + ~QPDFFileSpecObjectHelper() override = default; + + QPDF_DLL + std::string getDescription(); + + // Get the main filename for this file specification. In priority order, check /UF, /F, /Unix, + // /DOS, /Mac. + QPDF_DLL + std::string getFilename(); + + // Return any of /UF, /F, /Unix, /DOS, /Mac filename keys that may be present in the object. + QPDF_DLL + std::map getFilenames(); + + // Get the requested embedded file stream for this file specification. If key is empty, In + // priority order, check /UF, /F, /Unix, /DOS, /Mac. Returns a null object if not found. If this + // is an actual embedded file stream, its data is the content of the attachment. You can also + // use QPDFEFStreamObjectHelper for higher level access to the parameters. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStream(std::string const& key = ""); + + // Return the /EF key of the file spec, which is a map from file name key to embedded file + // stream. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStreams(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // fsoh.setDescription(x).setFilename(y); + + // Create a new filespec as an indirect object with the given filename, and attach the contents + // of the specified file as data in an embedded file stream. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, std::string const& fullpath); + + // Create a new filespec as an indirect object with the given unicode filename and embedded file + // stream. The file name will be used as both /UF and /F. If you need to override, call + // setFilename. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper); + + QPDF_DLL + QPDFFileSpecObjectHelper& setDescription(std::string const&); + // setFilename sets /UF to unicode_name. If compat_name is empty, it is also set to + // unicode_name. unicode_name should be a UTF-8 encoded string. compat_name is converted to a + // string QPDFObjectHandle literally, preserving whatever encoding it might happen to have. + QPDF_DLL + QPDFFileSpecObjectHelper& + setFilename(std::string const& unicode_name, std::string const& compat_name = ""); + + private: + class Members; + std::shared_ptr m; +}; + +#endif // QPDFFILESPECOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFFormFieldObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFFormFieldObjectHelper.hh new file mode 100644 index 0000000..a929563 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFFormFieldObjectHelper.hh @@ -0,0 +1,195 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFORMFIELDOBJECTHELPER_HH +#define QPDFFORMFIELDOBJECTHELPER_HH + +#include + +#include +#include + +class QPDFAnnotationObjectHelper; + +// This object helper helps with form fields for interactive forms. Please see comments in +// QPDFAcroFormDocumentHelper.hh for additional details. +class QPDFFormFieldObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFormFieldObjectHelper(); + QPDF_DLL + QPDFFormFieldObjectHelper(QPDFObjectHandle); + + ~QPDFFormFieldObjectHelper() override = default; + + QPDF_DLL + bool isNull(); + + // Return the field's parent. A form field object helper whose underlying object is null is + // returned if there is no parent. This condition may be tested by calling isNull(). + QPDF_DLL + QPDFFormFieldObjectHelper getParent(); + + // Return the top-level field for this field. Typically this will be the field itself or its + // parent. If is_different is provided, it is set to true if the top-level field is different + // from the field itself; otherwise it is set to false. + QPDF_DLL + QPDFFormFieldObjectHelper getTopLevelField(bool* is_different = nullptr); + + // Get a field value, possibly inheriting the value from an ancestor node. + QPDF_DLL + QPDFObjectHandle getInheritableFieldValue(std::string const& name); + + // Get an inherited field value as a string. If it is not a string, silently return the empty + // string. + QPDF_DLL + std::string getInheritableFieldValueAsString(std::string const& name); + + // Get an inherited field value of type name as a string representing the name. If it is not a + // name, silently return the empty string. + QPDF_DLL + std::string getInheritableFieldValueAsName(std::string const& name); + + // Returns the value of /FT if present, otherwise returns the empty string. + QPDF_DLL + std::string getFieldType(); + + QPDF_DLL + std::string getFullyQualifiedName(); + + QPDF_DLL + std::string getPartialName(); + + // Return the alternative field name (/TU), which is the field name intended to be presented to + // users. If not present, fall back to the fully qualified name. + QPDF_DLL + std::string getAlternativeName(); + + // Return the mapping field name (/TM). If not present, fall back to the alternative name, then + // to the partial name. + QPDF_DLL + std::string getMappingName(); + + QPDF_DLL + QPDFObjectHandle getValue(); + + // Return the field's value as a string. If this is called with a field whose value is not a + // string, the empty string will be silently returned. + QPDF_DLL + std::string getValueAsString(); + + QPDF_DLL + QPDFObjectHandle getDefaultValue(); + + // Return the field's default value as a string. If this is called with a field whose value is + // not a string, the empty string will be silently returned. + QPDF_DLL + std::string getDefaultValueAsString(); + + // Return the default appearance string, taking inheritance from the field tree into account. + // Returns the empty string if the default appearance string is not available (because it's + // erroneously absent or because this is not a variable text field). If not found in the field + // hierarchy, look in /AcroForm. + QPDF_DLL + std::string getDefaultAppearance(); + + // Return the default resource dictionary for the field. This comes not from the field but from + // the document-level /AcroForm dictionary. While several PDF generators put a /DR key in the + // form field's dictionary, experimentation suggests that many popular readers, including Adobe + // Acrobat and Acrobat Reader, ignore any /DR item on the field. + QPDF_DLL + QPDFObjectHandle getDefaultResources(); + + // Return the quadding value, taking inheritance from the field tree into account. Returns 0 if + // quadding is not specified. Look in /AcroForm if not found in the field hierarchy. + QPDF_DLL + int getQuadding(); + + // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as defined in + // qpdf/Constants.h + QPDF_DLL + int getFlags(); + + // Methods for testing for particular types of form fields + + // Returns true if field is of type /Tx + QPDF_DLL + bool isText(); + // Returns true if field is of type /Btn and flags do not indicate some other type of button. + QPDF_DLL + bool isCheckbox(); + // Returns true if field is a checkbox and is checked. + QPDF_DLL + bool isChecked(); + // Returns true if field is of type /Btn and flags indicate that it is a radio button + QPDF_DLL + bool isRadioButton(); + // Returns true if field is of type /Btn and flags indicate that it is a pushbutton + QPDF_DLL + bool isPushbutton(); + // Returns true if field is of type /Ch + QPDF_DLL + bool isChoice(); + // Returns choices display values as UTF-8 strings + QPDF_DLL + std::vector getChoices(); + + // Set an attribute to the given value. If you have a QPDFAcroFormDocumentHelper and you want to + // set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, QPDFObjectHandle value); + + // Set an attribute to the given value as a Unicode string (UTF-16 BE encoded). The input string + // should be UTF-8 encoded. If you have a QPDFAcroFormDocumentHelper and you want to set the + // name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, std::string const& utf8_value); + + // Set /V (field value) to the given value. If need_appearances is true and the field type is + // either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this + // method not to set /NeedAppearances if you are going to generate an appearance stream + // yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes, + // radio buttons, pushbuttons) specially. When setting a checkbox value, any value other than + // /Off will be treated as on, and the actual value set will be based on the appearance stream's + // /N dictionary, so the value that ends up in /V may not exactly match the value you pass in. + QPDF_DLL + void setV(QPDFObjectHandle value, bool need_appearances = true); + + // Set /V (field value) to the given string value encoded as a Unicode string. The input value + // should be UTF-8 encoded. See comments above about /NeedAppearances. + QPDF_DLL + void setV(std::string const& utf8_value, bool need_appearances = true); + + // Update the appearance stream for this field. Note that qpdf's ability to generate appearance + // streams is limited. We only generate appearance streams for streams of type text or choice. + // The appearance uses the default parameters provided in the file, and it only supports ASCII + // characters. Quadding is currently ignored. While this functionality is limited, it should do + // a decent job on properly constructed PDF files when field values are restricted to ASCII + // characters. + QPDF_DLL + void generateAppearance(QPDFAnnotationObjectHelper&); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFFORMFIELDOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFJob.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFJob.hh new file mode 100644 index 0000000..cace443 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFJob.hh @@ -0,0 +1,542 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFJOB_HH +#define QPDFJOB_HH + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFWriter; +class Pipeline; +class QPDFLogger; + +class QPDFJob +{ + public: + static int constexpr LATEST_JOB_JSON = 1; + + // Exit codes -- returned by getExitCode() after calling run() + static int constexpr EXIT_ERROR = qpdf_exit_error; + static int constexpr EXIT_WARNING = qpdf_exit_warning; + // For is-encrypted and requires-password + static int constexpr EXIT_IS_NOT_ENCRYPTED = qpdf_exit_is_not_encrypted; + static int constexpr EXIT_CORRECT_PASSWORD = qpdf_exit_correct_password; + + // QPDFUsage is thrown if there are any usage-like errors when calling Config methods. + QPDF_DLL + QPDFJob(); + + // SETUP FUNCTIONS + + // Initialize a QPDFJob object from argv, which must be a null-terminated array of + // null-terminated UTF-8-encoded C strings. The progname_env argument is the name of an + // environment variable which, if set, overrides the name of the executable for purposes of + // generating the --completion options. See QPDFArgParser for details. If a null pointer is + // passed in, the default value of "QPDF_EXECUTABLE" is used. This is used by the QPDF cli, + // which just initializes a QPDFJob from argv, calls run(), and handles errors and exit status + // issues. You can perform much of the cli functionality programmatically in this way rather + // than using the regular API. This is exposed in the C API, which makes it easier to get + // certain high-level qpdf functionality from other languages. If there are any command-line + // errors, this method will throw QPDFUsage which is derived from std::runtime_error. Other + // exceptions may be thrown in some cases. Note that argc, and argv should be UTF-8 encoded. If + // you are calling this from a Windows Unicode-aware main (wmain), see + // QUtil::call_main_from_wmain for information about converting arguments to UTF-8. This method + // will mutate arguments that are passed to it. + QPDF_DLL + void initializeFromArgv(char const* const argv[], char const* progname_env = nullptr); + + // Initialize a QPDFJob from json. Passing partial = true prevents this method from doing the + // final checks (calling checkConfiguration) after processing the json file. This makes it + // possible to initialize QPDFJob in stages using multiple json files or to have a json file + // that can be processed from the CLI with --job-json-file and be combined with other arguments. + // For example, you might include only encryption parameters, leaving it up to the rest of the + // command-line arguments to provide input and output files. initializeFromJson is called with + // partial = true when invoked from the command line. To make sure that the json file is fully + // valid on its own, just don't specify any other command-line flags. If there are any + // configuration errors, QPDFUsage is thrown. Some error messages may be CLI-centric. If an + // exception tells you to use the "--some-option" option, set the "someOption" key in the JSON + // object instead. + QPDF_DLL + void initializeFromJson(std::string const& json, bool partial = false); + + // Set name that is used to prefix verbose messages, progress messages, and other things that + // the library writes to output and error streams on the caller's behalf. Defaults to "qpdf". + QPDF_DLL + void setMessagePrefix(std::string const&); + QPDF_DLL + std::string getMessagePrefix() const; + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // If you set a custom logger here, the logger will be passed to all subsequent QPDF objects + // created by this QPDFJob object. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // You can register a custom progress reporter to be called by QPDFWriter (see + // QPDFWriter::registerProgressReporter). This is only called if you also request progress + // reporting through normal configuration methods (e.g., pass --progress, call + // config()->progress, etc.) + QPDF_DLL + void registerProgressReporter(std::function); + + // Check to make sure no contradictory options have been specified. This is called automatically + // after initializing from argv or json and is also called by run, but you can call it manually + // as well. It throws a QPDFUsage exception if there are any errors. This Config object (see + // CONFIGURATION) also has a checkConfiguration method which calls this one. + QPDF_DLL + void checkConfiguration(); + + // Returns true if output is created by the specified job. + QPDF_DLL + bool createsOutput() const; + + // SEE BELOW FOR MORE PUBLIC METHODS AND CLASSES + private: + // These structures are private but we need to define them before the public Config classes. + struct CopyAttachmentFrom + { + std::string path; + std::string password; + std::string prefix; + }; + + struct AddAttachment + { + std::string path; + std::string key; + std::string filename; + std::string creationdate; + std::string moddate; + std::string mimetype; + std::string description; + bool replace{false}; + }; + + public: + // CONFIGURATION + + // Configuration classes are implemented in QPDFJob_config.cc. + + // The config() method returns a shared pointer to a Config object. The Config object contains + // methods that correspond with qpdf command-line arguments. You can use a fluent interface to + // configure a QPDFJob object that would do exactly the same thing as a specific qpdf command. + // The example qpdf-job.cc contains an example of this usage. You can also use + // initializeFromJson or initializeFromArgv to initialize a QPDFJob object. + + // Notes about the Config methods: + // + // * Most of the method declarations are automatically generated in header files that are + // included within the class definitions. They correspond in predictable ways to the + // command-line arguments and are generated from the same code that generates the command-line + // argument parsing code. + // + // * Methods return pointers, rather than references, to configuration objects. References + // might feel more familiar to users of fluent interfaces, so why do we use pointers? The + // main methods that create them return smart pointers so that users can initialize them when + // needed, which you can't do with references. Returning pointers instead of references makes + // for a more uniform interface. + + // Maintainer documentation: see the section in README-maintainer called "HOW TO ADD A + // COMMAND-LINE ARGUMENT", which contains references to additional places in the documentation. + + class Config; + + class AttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endAddAttachment(); + QPDF_DLL + AttConfig* file(std::string const& parameter); + +#include + + private: + AttConfig(Config*); + AttConfig(AttConfig const&) = delete; + + Config* config; + AddAttachment att; + }; + + class CopyAttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endCopyAttachmentsFrom(); + QPDF_DLL + CopyAttConfig* file(std::string const& parameter); + +#include + + private: + CopyAttConfig(Config*); + CopyAttConfig(CopyAttConfig const&) = delete; + + Config* config; + CopyAttachmentFrom caf; + }; + + class PagesConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endPages(); + // From qpdf 11.9.0, you can call file(), range(), and password(). Each call to file() + // starts a new page spec. + QPDF_DLL + PagesConfig* pageSpec( + std::string const& filename, std::string const& range, char const* password = nullptr); + +#include + + private: + PagesConfig(Config*); + PagesConfig(PagesConfig const&) = delete; + + Config* config; + }; + + class UOConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endUnderlayOverlay(); + +#include + + private: + UOConfig(Config*); + UOConfig(UOConfig const&) = delete; + + Config* config; + }; + + class EncConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endEncrypt(); + QPDF_DLL + EncConfig* file(std::string const& parameter); + +#include + + private: + EncConfig(Config*); + EncConfig(EncConfig const&) = delete; + + Config* config; + }; + + class PageLabelsConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endSetPageLabels(); + +#include + + private: + PageLabelsConfig(Config*); + PageLabelsConfig(PageLabelsConfig const&) = delete; + + Config* config; + }; + + class GlobalConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endGlobal(); + +#include + + GlobalConfig(Config*); // for qpdf internal use only + GlobalConfig(GlobalConfig const&) = delete; + + private: + Config* config; + }; + + class Config + { + friend class QPDFJob; + + public: + // Proxy to QPDFJob::checkConfiguration() + QPDF_DLL + void checkConfiguration(); + + QPDF_DLL + Config* inputFile(std::string const& filename); + QPDF_DLL + Config* emptyInput(); + QPDF_DLL + Config* outputFile(std::string const& filename); + QPDF_DLL + Config* replaceInput(); + QPDF_DLL + Config* setPageLabels(std::vector const& specs); + + QPDF_DLL + std::shared_ptr copyAttachmentsFrom(); + QPDF_DLL + std::shared_ptr addAttachment(); + QPDF_DLL + std::shared_ptr global(); + QPDF_DLL + std::shared_ptr pages(); + QPDF_DLL + std::shared_ptr overlay(); + QPDF_DLL + std::shared_ptr underlay(); + QPDF_DLL + std::shared_ptr + encrypt(int keylen, std::string const& user_password, std::string const& owner_password); + +#include + + private: + Config() = delete; + Config(Config const&) = delete; + Config(QPDFJob& job) : + o(job) + { + } + QPDFJob& o; + }; + + // Return a top-level configuration item. See CONFIGURATION above for details. If an invalid + // configuration is created (such as supplying contradictory options, omitting an input file, + // etc.), QPDFUsage is thrown. Note that error messages are CLI-centric, but you can map them + // into config calls. For example, if an exception tells you to use the --some-option flag, you + // should call config()->someOption() instead. + QPDF_DLL + std::shared_ptr config(); + + // Execute the job + QPDF_DLL + void run(); + + // The following two methods allow a job to be run in two stages - creation of a QPDF object and + // writing of the QPDF object. This allows the QPDF object to be modified prior to writing it + // out. See examples/qpdfjob-remove-annotations for an illustration of its use. + + // Run the first stage of the job. Return a nullptr if the configuration is not valid. + QPDF_DLL + std::unique_ptr createQPDF(); + + // Run the second stage of the job. Do nothing if a nullptr is passed as parameter. + QPDF_DLL + void writeQPDF(QPDF& qpdf); + + // CHECK STATUS -- these methods provide information known after run() is called. + + QPDF_DLL + bool hasWarnings() const; + + // Return one of the EXIT_* constants defined at the top of the class declaration. This may be + // called after run() when run() did not throw an exception. Takes into consideration whether + // isEncrypted or requiresPassword was called. Note that this function does not know whether + // run() threw an exception, so code that uses this to determine how to exit should explicitly + // use EXIT_ERROR if run() threw an exception. + QPDF_DLL + int getExitCode() const; + + // Return value is bitwise OR of values from qpdf_encryption_status_e + QPDF_DLL + unsigned long getEncryptionStatus(); + + // HELPER FUNCTIONS -- methods useful for calling in handlers that interact with QPDFJob during + // run or initialization. + + // If in verbose mode, call the given function, passing in the output stream and message prefix. + QPDF_DLL + void doIfVerbose(std::function fn); + + // Provide a string that is the help information ("schema" for the qpdf-specific JSON object) + // for the specified version of JSON output. + QPDF_DLL + static std::string json_out_schema(int version); + + [[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL json_out_schema_v1(); + + // Provide a string that is the help information for specified version of JSON format for + // QPDFJob. + QPDF_DLL + static std::string job_json_schema(int version); + + [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1(); + + private: + struct PageNo; + struct Selection; + struct Input; + struct Inputs; + struct RotationSpec; + struct UnderOverlay; + struct PageLabelSpec; + + enum password_mode_e { pm_bytes, pm_hex_bytes, pm_unicode, pm_auto }; + + // Helper functions + static void usage(std::string const& msg); + static JSON json_schema(int json_version, std::set* keys = nullptr); + static void parse_object_id(std::string const& objspec, bool& trailer, int& obj, int& gen); + void parseRotationParameter(std::string const&); + std::vector parseNumrange(char const* range, int max); + + // Basic file processing + void processFile( + std::unique_ptr&, + char const* filename, + char const* password, + bool used_for_input, + bool main_input); + void processInputSource( + std::unique_ptr&, + std::shared_ptr is, + char const* password, + bool used_for_input); + void doProcess( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + void doProcessOnce( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + + // Transformations + void handlePageSpecs(QPDF& pdf); + bool shouldRemoveUnreferencedResources(QPDF& pdf); + void handleRotations(QPDF& pdf); + void getUOPagenos( + std::vector& uo, std::vector>>& pagenos); + void handleUnderOverlay(QPDF& pdf); + std::string doUnderOverlayForPage( + QPDF& pdf, + UnderOverlay& uo, + std::vector>>& pagenos, + PageNo const& page_idx, + size_t uo_idx, + std::map>& fo, + QPDFPageObjectHelper& dest_page); + void validateUnderOverlay(QPDF& pdf, UnderOverlay* uo); + void handleTransformations(QPDF& pdf); + void addAttachments(QPDF& pdf); + void copyAttachments(QPDF& pdf); + + // Inspection + void doInspection(QPDF& pdf); + void doCheck(QPDF& pdf); + void showEncryption(QPDF& pdf); + void doShowObj(QPDF& pdf); + void doShowPages(QPDF& pdf); + void doListAttachments(QPDF& pdf); + void doShowAttachment(QPDF& pdf); + + // Output generation + void doSplitPages(QPDF& pdf); + void setWriterOptions(qpdf::Writer&); + void setEncryptionOptions(QPDFWriter&); + void maybeFixWritePassword(int R, std::string& password); + void writeOutfile(QPDF& pdf); + void writeJSON(QPDF& pdf); + + // JSON + void doJSON(QPDF& pdf, Pipeline*); + QPDFObjGen::set getWantedJSONObjects(); + void doJSONObjects(Pipeline* p, bool& first, QPDF& pdf); + void doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPages(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPageLabels(Pipeline* p, bool& first, QPDF& pdf); + void doJSONOutlines(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAcroform(Pipeline* p, bool& first, QPDF& pdf); + void doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf); + void addOutlinesToJson( + std::vector outlines, + JSON& j, + std::map& page_numbers); + + enum remove_unref_e { re_auto, re_yes, re_no }; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOBJECT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFLogger.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFLogger.hh new file mode 100644 index 0000000..1e360be --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFLogger.hh @@ -0,0 +1,164 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFLOGGER_HH +#define QPDFLOGGER_HH + +#include +#include +#include +#include + +class QPDFLogger +{ + public: + QPDF_DLL + static std::shared_ptr create(); + + // Return the default logger. In general, you should use the default logger. You can also create + // your own loggers and use them with QPDF and QPDFJob objects, but there are few reasons to do + // so. One reason may be that you are using multiple QPDF or QPDFJob objects in different + // threads and want to capture output and errors to different streams. (Note that a single QPDF + // or QPDFJob can't be safely used from multiple threads, but it is safe to use separate QPDF + // and QPDFJob objects on separate threads.) Another possible reason would be if you are writing + // an application that uses the qpdf library directly and qpdf is also used by a downstream + // library or if you are using qpdf from a library and don't want to interfere with potential + // uses of qpdf by other libraries or applications. + QPDF_DLL + static std::shared_ptr defaultLogger(); + + // Defaults: + // + // info -- if save is standard output, standard error, else standard output + // warn -- whatever error points to + // error -- standard error + // save -- undefined unless set + // + // "info" is used for diagnostic messages, verbose messages, and progress messages. "warn" is + // used for warnings. "error" is used for errors. "save" is used for saving output -- see below. + // + // On deletion, finish() is called for the standard output and standard error pipelines, which + // flushes output. If you supply any custom pipelines, you must call finish() on them yourself. + // Note that calling finish is not needed for string, stdio, or ostream pipelines. + // + // NOTES ABOUT THE SAVE PIPELINE + // + // The save pipeline is used by QPDFJob when some kind of binary output is being saved. This + // includes saving attachments and stream data and also includes when the output file is + // standard output. If you want to grab that output, you can call setSave. See + // examples/qpdfjob-save-attachment.cc and examples/qpdfjob-c-save-attachment.c. + // + // You should never set the save pipeline to the same destination as something else. Doing so + // will corrupt your save output. If you want to save to standard output, use the method + // saveToStandardOutput(). In addition to setting the save pipeline, that does the following + // extra things: + // + // * If standard output has been used, a logic error is thrown + // * If info is set to standard output at the time of the set save call, it is switched to + // standard error. + // + // This is not a guarantee. You can still mess this up in ways that are not checked. Here are a + // few examples: + // + // * Don't set any pipeline to standard output *after* passing it to setSave() + // * Don't use a separate mechanism to write stdout/stderr other than + // QPDFLogger::standardOutput() + // * Don't set anything to the same custom pipeline that save is set to. + // + // Just be sure that if you change pipelines around, you should avoid having the save pipeline + // also be used for any other purpose. The special case for saving to standard output allows you + // to call saveToStandardOutput() early without having to worry about the info pipeline. + + QPDF_DLL + void info(char const*); + QPDF_DLL + void info(std::string const&); + QPDF_DLL + std::shared_ptr getInfo(bool null_okay = false); + + QPDF_DLL + void warn(char const*); + QPDF_DLL + void warn(std::string const&); + QPDF_DLL + std::shared_ptr getWarn(bool null_okay = false); + + QPDF_DLL + void error(char const*); + QPDF_DLL + void error(std::string const&); + QPDF_DLL + std::shared_ptr getError(bool null_okay = false); + + QPDF_DLL + std::shared_ptr getSave(bool null_okay = false); + + QPDF_DLL + std::shared_ptr standardOutput(); + QPDF_DLL + std::shared_ptr standardError(); + QPDF_DLL + std::shared_ptr discard(); + + // Passing a null pointer resets to default + QPDF_DLL + void setInfo(std::shared_ptr); + QPDF_DLL + void setWarn(std::shared_ptr); + QPDF_DLL + void setError(std::shared_ptr); + // See notes above about the save pipeline + QPDF_DLL + void setSave(std::shared_ptr, bool only_if_not_set); + QPDF_DLL + void saveToStandardOutput(bool only_if_not_set); + + // Shortcut for logic to reset output to new output/error streams. out_stream is used for info, + // err_stream is used for error, and warning is cleared so that it follows error. + QPDF_DLL + void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + private: + QPDFLogger(); + std::shared_ptr throwIfNull(std::shared_ptr, bool null_okay); + + class Members + { + friend class QPDFLogger; + + public: + ~Members(); + + private: + Members(); + Members(Members const&) = delete; + + std::shared_ptr p_discard; + std::shared_ptr p_real_stdout; + std::shared_ptr p_stdout; + std::shared_ptr p_stderr; + std::shared_ptr p_info; + std::shared_ptr p_warn; + std::shared_ptr p_error; + std::shared_ptr p_save; + }; + std::shared_ptr m; +}; + +#endif // QPDFLOGGER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFMatrix.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFMatrix.hh new file mode 100644 index 0000000..37624df --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFMatrix.hh @@ -0,0 +1,93 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFMATRIX_HH +#define QPDFMATRIX_HH + +#include +#include +#include + +// This class represents a PDF transformation matrix using a tuple such that +// +// ┌ ┐ +// │ a b 0 │ +// (a, b, c, d, e, f) = │ c d 0 │ +// │ e f 1 │ +// └ ┘ +class QPDFMatrix +{ + public: + QPDF_DLL + QPDFMatrix(); + QPDF_DLL + QPDFMatrix(double a, double b, double c, double d, double e, double f); + QPDF_DLL + QPDFMatrix(QPDFObjectHandle::Matrix const&); + + // Returns the six values separated by spaces as real numbers with trimmed zeroes. + QPDF_DLL + std::string unparse() const; + + QPDF_DLL + QPDFObjectHandle::Matrix getAsMatrix() const; + + // Replace this with other * this + QPDF_DLL + void concat(QPDFMatrix const& other); + + // Same as concat(sx, 0, 0, sy, 0, 0) + QPDF_DLL + void scale(double sx, double sy); + + // Same as concat(1, 0, 0, 1, tx, ty); + QPDF_DLL + void translate(double tx, double ty); + + // Any value other than 90, 180, or 270 is ignored + QPDF_DLL + void rotatex90(int angle); + + // Transform a point. The underlying operation is to take + // [x y 1] * this + // and take the first and second rows of the result as xp and yp. + QPDF_DLL + void transform(double x, double y, double& xp, double& yp) const; + + // Transform a rectangle by creating a new rectangle that tightly bounds the polygon resulting + // from transforming the four corners. + QPDF_DLL + QPDFObjectHandle::Rectangle transformRectangle(QPDFObjectHandle::Rectangle r) const; + + // operator== tests for exact equality, not considering deltas for floating point. + QPDF_DLL + bool operator==(QPDFMatrix const& rhs) const; + + QPDF_DLL + bool operator!=(QPDFMatrix const& rhs) const; + + double a; + double b; + double c; + double d; + double e; + double f; +}; + +#endif // QPDFMATRIX_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFNameTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFNameTreeObjectHelper.hh new file mode 100644 index 0000000..7677819 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFNameTreeObjectHelper.hh @@ -0,0 +1,184 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNAMETREEOBJECTHELPER_HH +#define QPDFNAMETREEOBJECTHELPER_HH + +#include +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for name trees. See section 7.9.6 in the PDF spec (ISO 32000) for a +// description of name trees. When looking up items in the name tree, use UTF-8 strings. All names +// are normalized for lookup purposes. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNameTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNameTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Create an empty name tree + QPDF_DLL + static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + QPDF_DLL + ~QPDFNameTreeObjectHelper() override; + + // Return whether the name tree has an explicit entry for this name. + QPDF_DLL + bool hasName(std::string const& utf8); + + // Find an object by name. If found, returns true and initializes oh. See also find(). + QPDF_DLL + bool findObject(std::string const& utf8, QPDFObjectHandle& oh); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNameTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(std::string const& key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a string and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(std::string const& key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(std::string const& key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(std::string const& key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the name tree as a map. Note that name trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNameTreeObjectHelper's iterator. + QPDF_DLL + std::map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNAMETREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFNumberTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFNumberTreeObjectHelper.hh new file mode 100644 index 0000000..b7d7716 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFNumberTreeObjectHelper.hh @@ -0,0 +1,200 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNUMBERTREEOBJECTHELPER_HH +#define QPDFNUMBERTREEOBJECTHELPER_HH + +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for number trees. See section 7.9.7 in the PDF spec (ISO 32000) for a +// description of number trees. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNumberTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNumberTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + QPDF_DLL + ~QPDFNumberTreeObjectHelper() override; + + // Create an empty number tree + QPDF_DLL + static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + typedef long long int numtree_number; + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Return overall minimum and maximum indices + QPDF_DLL + numtree_number getMin(); + QPDF_DLL + numtree_number getMax(); + + // Return whether the number tree has an explicit entry for this number. + QPDF_DLL + bool hasIndex(numtree_number idx); + + // Find an object with a specific index. If found, returns true and initializes oh. See also + // find(). + QPDF_DLL + bool findObject(numtree_number idx, QPDFObjectHandle& oh); + // Find the object at the index or, if not found, the object whose index is the highest index + // less than the requested index. If the requested index is less than the minimum, return false. + // Otherwise, return true, initialize oh to the object, and set offset to the difference between + // the requested index and the actual index. For example, if a number tree has values for 3 and + // 6 and idx is 5, this method would return true, initialize oh to the value with index 3, and + // set offset to 2 (5 - 3). See also find(). + QPDF_DLL + bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNumberTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(numtree_number key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a numtree_number and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(numtree_number key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(numtree_number key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(numtree_number key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the number tree as a map. Note that number trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNumberTreeObjectHelper's iterator. + typedef std::map idx_map; + QPDF_DLL + idx_map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNUMBERTREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjGen.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjGen.hh new file mode 100644 index 0000000..1f92488 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjGen.hh @@ -0,0 +1,137 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJGEN_HH +#define QPDFOBJGEN_HH + +#include + +#include +#include +#include + +class QPDFObjectHandle; +class QPDFObjectHelper; + +// This class represents an object ID and generation pair. It is suitable to use as a key in a map +// or set. + +class QPDFObjGen +{ + public: + QPDFObjGen() = default; + QPDFObjGen(int obj, int gen) : + obj(obj), + gen(gen) + { + } + bool + operator<(QPDFObjGen const& rhs) const + { + return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen); + } + bool + operator==(QPDFObjGen const& rhs) const + { + return obj == rhs.obj && gen == rhs.gen; + } + bool + operator!=(QPDFObjGen const& rhs) const + { + return !(*this == rhs); + } + int + getObj() const + { + return obj; + } + int + getGen() const + { + return gen; + } + bool + isIndirect() const + { + return obj != 0; + } + std::string + unparse(char separator = ',') const + { + return std::to_string(obj) + separator + std::to_string(gen); + } + friend std::ostream& + operator<<(std::ostream& os, QPDFObjGen og) + { + os << og.obj << "," << og.gen; + return os; + } + + // Convenience class for loop detection when processing objects. + // + // The class adds 'add' methods to a std::set which allows to test whether an + // QPDFObjGen is present in the set and to insert it in a single operation. The 'add' method is + // overloaded to take a QPDFObjGen, QPDFObjectHandle or an QPDFObjectHelper as parameter. + // + // The erase method is modified to ignore requests to erase QPDFObjGen(0, 0). + // + // Usage example: + // + // void process_object(QPDFObjectHandle oh, QPDFObjGen::set& seen) + // { + // if (seen.add(oh)) { + // // handle first encounter of oh + // } else { + // // handle loop / subsequent encounter of oh + // } + // } + class QPDF_DLL_CLASS set: public std::set + { + public: + // Add 'og' to the set. Return false if 'og' is already present in the set. Attempts to + // insert QPDFObjGen(0, 0) are ignored. + bool + add(QPDFObjGen og) + { + if (og.isIndirect()) { + if (count(og)) { + return false; + } + emplace(og); + } + return true; + } + + void + erase(QPDFObjGen og) + { + if (og.isIndirect()) { + std::set::erase(og); + } + } + }; + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created and destroyed. + int obj{0}; + int gen{0}; +}; + +#endif // QPDFOBJGEN_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObject.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObject.hh new file mode 100644 index 0000000..8499637 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObject.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECT_OLD_HH +#define QPDFOBJECT_OLD_HH + +// Current code should not include . This file exists +// to ensure that code that includes it doesn't accidentally work because +// of an old qpdf installed on the system. Including this file became an +// error with qpdf version 12. The internal QPDFObject API is defined in +// QPDFObject_private.hh, which is not part of the public API. + +// Instead of including this header, include , and +// replace `QPDFObject::ot_` with `::ot_` in your code. +#error "QPDFObject.hh is obsolete; see comments in QPDFObject.hh for details" + +#endif // QPDFOBJECT_OLD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjectHandle.hh new file mode 100644 index 0000000..9fef4e6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjectHandle.hh @@ -0,0 +1,1576 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECTHANDLE_HH +#define QPDFOBJECTHANDLE_HH + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class Pipeline; +class QPDF_Array; +class QPDF_Bool; +class QPDF_Dictionary; +class QPDF_InlineImage; +class QPDF_Integer; +class QPDF_Name; +class QPDF_Null; +class QPDF_Operator; +class QPDF_Real; +class QPDF_Reserved; +class QPDF_Stream; +class QPDF_String; +class QPDFObject; +class QPDFObjectHandle; +class QPDFTokenizer; +class QPDFExc; +class Pl_QPDFTokenizer; +class QPDFMatrix; +namespace qpdf::impl +{ + class Parser; +} + +class QPDFObjectHandle: public qpdf::BaseHandle +{ + friend class qpdf::impl::Parser; + + public: + // This class is used by replaceStreamData. It provides an alternative way of associating + // stream data with a stream. See comments on replaceStreamData and newStream for additional + // details. + class QPDF_DLL_CLASS StreamDataProvider + { + public: + QPDF_DLL + StreamDataProvider(bool supports_retry = false); + + QPDF_DLL + virtual ~StreamDataProvider(); + // The implementation of this function must write stream data to the given pipeline. The + // stream data must conform to whatever filters are explicitly associated with the stream. + // QPDFWriter may, in some cases, add compression, but if it does, it will update the + // filters as needed. Every call to provideStreamData for a given stream must write the same + // data. Note that, when writing linearized files, qpdf will call your provideStreamData + // twice, and if it generates different output, you risk generating invalid output or having + // qpdf throw an exception. The object ID and generation passed to this method are those + // that belong to the stream on behalf of which the provider is called. They may be ignored + // or used by the implementation for indexing or other purposes. This information is made + // available just to make it more convenient to use a single StreamDataProvider object to + // provide data for multiple streams. + + // A few things to keep in mind: + // + // * Stream data providers must not modify any objects since they may be called after some + // parts of the file have already been written. + // + // * Since qpdf may call provideStreamData multiple times when writing linearized files, if + // the work done by your stream data provider is slow or computationally intensive, you + // might want to implement your own cache. + // + // * Once you have called replaceStreamData, the original stream data is no longer directly + // accessible from the stream, but this is easy to work around by copying the stream to + // a separate QPDF object. The qpdf library implements this very efficiently without + // actually making a copy of the stream data. You can find examples of this pattern in + // some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc. + + // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or + // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by + // allowing an alternative provideStreamData to be implemented. You must implement at least + // one of the versions of provideStreamData below. If you implement the version that + // supports retry and returns a value, you should pass true as the value of supports_retry + // in the base class constructor. This will cause the library to call that version of the + // method, which should also return a boolean indicating whether it ran without errors. + QPDF_DLL + virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline); + QPDF_DLL + virtual bool provideStreamData( + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline); + QPDF_DLL virtual bool provideStreamData( + int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL + bool supportsRetry(); + + private: + bool supports_retry; + }; + + // The TokenFilter class provides a way to filter content streams in a lexically aware fashion. + // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter + // methods or can be applied on the spot by filterPageContents. You may also use + // Pl_QPDFTokenizer directly if you need full control. + // + // The handleToken method is called for each token, including the eof token, and then handleEOF + // is called at the very end. Handlers may call write (or writeToken) to pass data downstream. + // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of + // using TokenFilters. + // + // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you + // get the canonical, "parsed" representation of the token. For a string, this means that there + // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits) + // has been resolved. qpdf's internal representation of a name includes the leading slash. As + // such, you can't write the value of token.getValue() directly to output that is supposed to be + // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can + // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new + // string or name token from a canonical representation, use + // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or + // QPDFTokenizer::Token(QPDFTokenizer::tt_name, + // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can + // still write them with writeToken(). Example: + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain")) + // would write `/text#2fplain`, and + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`. + class QPDF_DLL_CLASS TokenFilter + { + public: + TokenFilter() = default; + virtual ~TokenFilter() = default; + virtual void handleToken(QPDFTokenizer::Token const&) = 0; + QPDF_DLL + virtual void handleEOF(); + + class PipelineAccessor + { + friend class Pl_QPDFTokenizer; + + private: + static void + setPipeline(TokenFilter* f, Pipeline* p) + { + f->setPipeline(p); + } + }; + + protected: + QPDF_DLL + void write(char const* data, size_t len); + QPDF_DLL + void write(std::string const& str); + QPDF_DLL + void writeToken(QPDFTokenizer::Token const&); + + private: + QPDF_DLL_PRIVATE + void setPipeline(Pipeline*); + + Pipeline* pipeline; + }; + + // This class is used by parse to decrypt strings when reading an object that contains encrypted + // strings. + class StringDecrypter + { + public: + virtual ~StringDecrypter() = default; + virtual void decryptString(std::string& val) = 0; + }; + + // This class is used by parsePageContents. Callers must instantiate a subclass of this with + // handlers defined to accept QPDFObjectHandles that are parsed from the stream. + class QPDF_DLL_CLASS ParserCallbacks + { + public: + virtual ~ParserCallbacks() = default; + // One of the handleObject methods must be overridden. + QPDF_DLL + virtual void handleObject(QPDFObjectHandle); + QPDF_DLL + virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length); + + virtual void handleEOF() = 0; + + // Override this if you want to know the full size of the contents, possibly after + // concatenation of multiple streams. This is called before the first call to handleObject. + QPDF_DLL + virtual void contentSize(size_t); + + protected: + // Implementors may call this method during parsing to terminate parsing early. This method + // throws an exception that is caught by parsePageContents, so its effect is immediate. + QPDF_DLL + void terminateParsing(); + }; + + // Convenience object for rectangles + class Rectangle + { + public: + Rectangle() : + llx(0.0), + lly(0.0), + urx(0.0), + ury(0.0) + { + } + Rectangle(double llx, double lly, double urx, double ury) : + llx(llx), + lly(lly), + urx(urx), + ury(ury) + { + } + + double llx; + double lly; + double urx; + double ury; + }; + + // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't + // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity + // transform matrix and this one is all zeroes. + class Matrix + { + public: + Matrix() : + a(0.0), + b(0.0), + c(0.0), + d(0.0), + e(0.0), + f(0.0) + { + } + Matrix(double a, double b, double c, double d, double e, double f) : + a(a), + b(b), + c(c), + d(d), + e(e), + f(f) + { + } + + double a; + double b; + double c; + double d; + double e; + double f; + }; + + QPDFObjectHandle() = default; + QPDFObjectHandle(QPDFObjectHandle const&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default; + QPDFObjectHandle(QPDFObjectHandle&&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default; + + // This method is provided for backward compatibility only. New code should convert to bool + // instead. + inline bool isInitialized() const; + + // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying + // object, meaning that changes to one are reflected in the other, or "if you paint one, the + // other one changes color." This does not perform a structural comparison of the contents of + // the objects. + QPDF_DLL + bool isSameObjectAs(QPDFObjectHandle const&) const; + + // Return type code and type name of underlying object. These are useful for doing rapid type + // tests (like switch statements) or for testing and debugging. + QPDF_DLL + qpdf_object_type_e getTypeCode() const; + QPDF_DLL + char const* getTypeName() const; + + // Exactly one of these will return true for any initialized object. Operator and InlineImage + // are only allowed in content streams. + QPDF_DLL + bool isBool() const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + bool isInteger() const; + QPDF_DLL + bool isReal() const; + QPDF_DLL + bool isName() const; + QPDF_DLL + bool isString() const; + QPDF_DLL + bool isOperator() const; + QPDF_DLL + bool isInlineImage() const; + QPDF_DLL + bool isArray() const; + QPDF_DLL + bool isDictionary() const; + QPDF_DLL + bool isStream() const; + QPDF_DLL + bool isReserved() const; + + // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended + // for internal use, but it can be used as an efficient way to check for nulls that are not + // indirect objects. + QPDF_DLL + bool isDirectNull() const; + + // This returns true in addition to the query for the specific type for indirect objects. + QPDF_DLL + bool isIndirect() const; + + // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse + // such an object will throw a logic_error. + QPDF_DLL + bool isDestroyed() const; + + // True for everything except array, dictionary, stream, word, and inline image. + QPDF_DLL + bool isScalar() const; + + // True if the object is a name object representing the provided name. + QPDF_DLL + bool isNameAndEquals(std::string const& name) const; + + // True if the object is a dictionary of the specified type and subtype, if any. + QPDF_DLL + bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const; + + // True if the object is a stream of the specified type and subtype, if any. + QPDF_DLL + bool isStreamOfType(std::string const& type, std::string const& subtype = "") const; + + // Public factory methods + + // Wrap an object in an array if it is not already an array. This is a helper for cases in which + // something in a PDF may either be a single item or an array of items, which is a common idiom. + QPDF_DLL + QPDFObjectHandle wrapInArray(); + + // Construct an object of any type from a string representation of the object. Throws QPDFExc + // with an empty filename and an offset into the string if there is an error. Any indirect + // object syntax (obj gen R) will cause a logic_error exception to be thrown. If + // object_description is provided, it will appear in the message of any QPDFExc exception thrown + // for invalid syntax. See also the global `operator ""_qpdf` defined below. + QPDF_DLL + static QPDFObjectHandle + parse(std::string const& object_str, std::string const& object_description = ""); + + // Construct an object of any type from a string representation of the object. Indirect object + // syntax (obj gen R) is allowed and will create indirect references within the passed-in + // context. If object_description is provided, it will appear in the message of any QPDFExc + // exception thrown for invalid syntax. Note that you can't parse an indirect object reference + // all by itself as parse will stop at the end of the first complete object, which will just be + // the first number and will report that there is trailing data at the end of the string. + QPDF_DLL + static QPDFObjectHandle + parse(QPDF* context, std::string const& object_str, std::string const& object_description = ""); + + // Construct an object as above by reading from the given InputSource at its current position + // and using the tokenizer you supply. Indirect objects and encrypted strings are permitted. + // This method was intended to be called by QPDF for parsing objects that are read from the + // object's input stream. To be removed in qpdf 13. See + // . + [[deprecated("to be removed in qpdf 13")]] QPDF_DLL static QPDFObjectHandle parse( + std::shared_ptr input, + std::string const& object_description, + QPDFTokenizer&, + bool& empty, + StringDecrypter* decrypter, + QPDF* context); + + // Return the offset where the object was found when parsed. A negative value means that the + // object was created without parsing. If the object is in a stream, the offset is from the + // beginning of the stream. Otherwise, the offset is from the beginning of the file. + QPDF_DLL + qpdf_offset_t getParsedOffset() const; + + // Older method: stream_or_array should be the value of /Contents from a page object. It's more + // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error + // messages will also be more useful because the page object information will be known. + QPDF_DLL + static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks); + + // When called on a stream or stream array that is some page's content streams, do the same as + // pipePageContents. This method is a lower level way to do what + // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a + // contents object that is disconnected from a page object. The description argument should + // describe the containing page and is used in error messages. The all_description argument is + // initialized to something that could be used to describe the result of the pipeline. It is the + // description amended with the identifiers of the underlying objects. Please note that if there + // is an array of content streams, p->finish() is called after each stream. If you pass a + // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an + // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the + // end. + QPDF_DLL + void + pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description); + + // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream + // data is passed through the token filter after all original filters but before content stream + // normalization if requested. This is a low-level interface to add it to a stream. You will + // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be + // applied to a page object, and which will automatically handle the case of pages whose + // contents are split across multiple streams. + QPDF_DLL + void addTokenFilter(std::shared_ptr token_filter); + + // Legacy helpers for parsing content streams. These methods are not going away, but newer code + // should call the correspond methods in QPDFPageObjectHelper instead. The specification and + // behavior of these methods are the same as the identically named methods in that class, but + // newer functionality will be added there. + QPDF_DLL + void parsePageContents(ParserCallbacks* callbacks); + QPDF_DLL + void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr); + // See comments for QPDFPageObjectHelper::pipeContents. + QPDF_DLL + void pipePageContents(Pipeline* p); + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + // End legacy content stream helpers + + // Called on a stream to filter the stream as if it were page contents. This can be used to + // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream. + QPDF_DLL + void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr); + // Called on a stream to parse the stream as page contents. This can be used to parse a form + // XObject. + QPDF_DLL + void parseAsContents(ParserCallbacks* callbacks); + + // Type-specific factories + QPDF_DLL + static QPDFObjectHandle newNull(); + QPDF_DLL + static QPDFObjectHandle newBool(bool value); + QPDF_DLL + static QPDFObjectHandle newInteger(long long value); + QPDF_DLL + static QPDFObjectHandle newReal(std::string const& value); + QPDF_DLL + static QPDFObjectHandle + newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true); + // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes, + // excluding the NUL character, and starting with a slash. Name objects as represented in the + // PDF specification can contain characters escaped with #, but such escaping is not of concern + // when calling QPDFObjectHandle methods not directly relating to parsing. For example, + // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return + // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse() + // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and + // modifying objects, you want to work with the internal, canonical representation. For names + // containing alphanumeric characters, dashes, and underscores, there is no difference between + // the two representations. For a lengthy discussion, see + // https://github.com/qpdf/qpdf/discussions/625. + QPDF_DLL + static QPDFObjectHandle newName(std::string const& name); + QPDF_DLL + static QPDFObjectHandle newString(std::string const& str); + // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in + // PDF files outside of content streams, such as in document metadata form field values, page + // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16 + // as needed to successfully encode all the characters. + QPDF_DLL + static QPDFObjectHandle newUnicodeString(std::string const& utf8_str); + QPDF_DLL + static QPDFObjectHandle newOperator(std::string const&); + QPDF_DLL + static QPDFObjectHandle newInlineImage(std::string const&); + QPDF_DLL + static QPDFObjectHandle newArray(); + QPDF_DLL + static QPDFObjectHandle newArray(std::vector const& items); + QPDF_DLL + static QPDFObjectHandle newArray(Rectangle const&); + QPDF_DLL + static QPDFObjectHandle newArray(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newArray(QPDFMatrix const&); + QPDF_DLL + static QPDFObjectHandle newDictionary(); + QPDF_DLL + static QPDFObjectHandle newDictionary(std::map const& items); + + // Create an array from a rectangle. Equivalent to the rectangle form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromRectangle(Rectangle const&); + // Create an array from a matrix. Equivalent to the matrix form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromMatrix(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newFromMatrix(QPDFMatrix const&); + + // Note: new stream creation methods have were added to the QPDF class starting with + // version 11.2.0. The ones in this class are here for backward compatibility. + + // Create a new stream and associate it with the given qpdf object. A subsequent call must be + // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be + // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively, + // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can + // call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf); + + // Create a new stream and associate it with the given qpdf object. Use the given buffer as the + // stream data. The stream dictionary's /Length key will automatically be set to the size of the + // data buffer. If additional keys are required, the stream's dictionary may be retrieved by + // calling getDict(), and the resulting dictionary may be modified. This method is just a + // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience + // methods for streams that require no parameters beyond the stream length. Note that you don't + // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will + // automatically compress uncompressed stream data. Example programs are provided that + // illustrate this. From QPDF 11.2, you can call QPDF::newStream() + // instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + // From QPDF 11.2, you can call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call + // QPDF::newReserved() instead. + QPDF_DLL + static QPDFObjectHandle newReserved(QPDF* qpdf); + + // Provide an owning qpdf and object description. The library does this automatically with + // objects that are read from the input PDF and with objects that are created programmatically + // and inserted into the QPDF as a new indirect object. Most end user code will not need to call + // this. If an object has an owning qpdf and object description, it enables qpdf to give + // warnings with proper context in some cases where it would otherwise raise exceptions. It is + // okay to add objects without an owning_qpdf to objects that have one, but it is an error to + // have a QPDF contain objects with owning_qpdf set to something else. To add objects from + // another qpdf, use copyForeignObject instead. + QPDF_DLL + void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description); + QPDF_DLL + bool hasObjectDescription() const; + + // Accessor methods + // + // (Note: this comment is referenced in qpdf-c.h and the manual.) + // + // In PDF files, objects have specific types, but there is nothing that prevents PDF files from + // containing objects of types that aren't expected by the specification. + // + // There are two flavors of accessor methods: + // + // * getSomethingValue() returns the value and issues a type warning if the type is incorrect. + // + // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns + // true and initializes a reference of the appropriate type. These methods never issue type + // warnings. + // + // The getSomethingValue() accessors and some of the other methods expect objects of a + // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as + // trying to get a dictionary key from an array, trying to get the string value of a number, + // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using + // the following behavior: + // + // * Requesting a value of the wrong type (int value from string, array item from a scalar or + // dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for + // number, the empty string for string, or the null object for an object handle. + // + // * Accessing an array item that is out of bounds will return a null object. + // + // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to + // a scalar or array) will be ignored. + // + // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5, + // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code + // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case + // for all objects whose origin was a PDF file), the warning is issued using the normal warning + // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them. + // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created + // programmatically), an exception will be thrown. + // + // The way to avoid getting any type warnings or exceptions, even when working with malformed + // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for + // example, make sure that isString() returns true before calling getStringValue()) and to + // always be sure that any array indices are in bounds. + // + // For additional discussion and rationale for this behavior, see the section in the QPDF manual + // entitled "Object Accessor Methods". + + // Methods for bool objects + QPDF_DLL + bool getBoolValue() const; + QPDF_DLL + bool getValueAsBool(bool&) const; + + // Methods for integer objects. Note: if an integer value is too big (too far away from zero in + // either direction) to fit in the requested return type, the maximum or minimum value for that + // return type may be returned. For example, on a system with 32-bit int, a numeric object with + // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX. + QPDF_DLL + long long getIntValue() const; + QPDF_DLL + bool getValueAsInt(long long&) const; + QPDF_DLL + int getIntValueAsInt() const; + QPDF_DLL + bool getValueAsInt(int&) const; + QPDF_DLL + unsigned long long getUIntValue() const; + QPDF_DLL + bool getValueAsUInt(unsigned long long&) const; + QPDF_DLL + unsigned int getUIntValueAsUInt() const; + QPDF_DLL + bool getValueAsUInt(unsigned int&) const; + + // Methods for real objects + QPDF_DLL + std::string getRealValue() const; + QPDF_DLL + bool getValueAsReal(std::string&) const; + + // Methods that work for both integer and real objects + QPDF_DLL + bool isNumber() const; + QPDF_DLL + double getNumericValue() const; + QPDF_DLL + bool getValueAsNumber(double&) const; + + // Methods for name objects. The returned name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + std::string getName() const; + QPDF_DLL + bool getValueAsName(std::string&) const; + + // Methods for string objects + QPDF_DLL + std::string getStringValue() const; + QPDF_DLL + bool getValueAsString(std::string&) const; + + // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise, + // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to + // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters + // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range + // unmapped. + QPDF_DLL + std::string getUTF8Value() const; + QPDF_DLL + bool getValueAsUTF8(std::string&) const; + + // Methods for content stream objects + QPDF_DLL + std::string getOperatorValue() const; + QPDF_DLL + bool getValueAsOperator(std::string&) const; + QPDF_DLL + std::string getInlineImageValue() const; + QPDF_DLL + bool getValueAsInlineImage(std::string&) const; + + // Methods for array objects; see also name and array objects. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.aitems()) + // { + // // iter is an array element + // } + class QPDFArrayItems; + QPDF_DLL + QPDFArrayItems aitems(); + + QPDF_DLL + int getArrayNItems() const; + QPDF_DLL + QPDFObjectHandle getArrayItem(int n) const; + // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling + // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of + // nulls. + QPDF_DLL + std::vector getArrayAsVector() const; + QPDF_DLL + bool isRectangle() const; + // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the + // rectangle [0, 0, 0, 0] + QPDF_DLL + Rectangle getArrayAsRectangle() const; + QPDF_DLL + bool isMatrix() const; + // If the array is an array of six numeric values, return as a matrix. Otherwise, return the + // matrix [1, 0, 0, 1, 0, 0] + QPDF_DLL + Matrix getArrayAsMatrix() const; + + // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as + // canonical name strings starting with a leading slash and not containing any PDF syntax + // escaping. See comments for getName() for details. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.ditems()) + // { + // // iter.first is the key + // // iter.second is the value + // } + class QPDFDictItems; + QPDF_DLL + QPDFDictItems ditems(); + + // Return true if key is present. Keys with null values are treated as if they are not present. + // This is as per the PDF spec. + QPDF_DLL + bool hasKey(std::string const&) const; + // Return the value for the key. If the key is not present, null is returned. + QPDF_DLL + QPDFObjectHandle getKey(std::string const&) const; + // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access + // lower-level dictionaries, as in + // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font"); + QPDF_DLL + QPDFObjectHandle getKeyIfDict(std::string const&) const; + // Return all keys. Keys with null values are treated as if they are not present. This is as + // per the PDF spec. + QPDF_DLL + std::set getKeys() const; + // Return dictionary as a map. Entries with null values are included. + QPDF_DLL + std::map getDictAsMap() const; + + // Methods for name and array objects. The name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + bool isOrHasName(std::string const&) const; + + // Make all resources in a resource dictionary indirect. This just goes through all entries of + // top-level subdictionaries and converts any direct objects to indirect objects. This can be + // useful to call before mergeResources if it is going to be called multiple times to prevent + // resources from being copied multiple times. + QPDF_DLL + void makeResourcesIndirect(QPDF& owning_qpdf); + + // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in + // dictionary subitems are resolved, and "conflicts" is initialized to a map such that + // conflicts[resource_type][old_key] == [new_key] + // + // See also makeResourcesIndirect, which can be useful to call before calling this. + // + // This method does nothing if both this object and the other object are not dictionaries. + // Otherwise, it has following behavior, where "object" refers to the object whose method is + // invoked, and "other" refers to the argument: + // + // * For each key in "other" whose value is an array: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, if "object" has an array in the same place, append to that array any objects + // in "other"'s array that are not already present. + // * For each key in "other" whose value is a dictionary: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, for each key in the subdictionary: + // * If key is not present in "object"'s entry, shallow copy it if direct or just add it if + // indirect. + // * Otherwise, if conflicts are being detected: + // * If there is a key (oldkey) already in the dictionary that points to the same indirect + // destination as key, indicate that key was replaced by oldkey. This would happen if + // these two resource dictionaries have previously been merged. + // * Otherwise pick a new key (newkey) that is unique within the resource dictionary, + // store that in the resource dictionary with key's destination as its destination, and + // indicate that key was replaced by newkey. + // + // The primary purpose of this method is to facilitate merging of resource dictionaries that are + // supposed to have the same scope as each other. For example, this can be used to merge a form + // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The + // "conflicts" parameter may be previously initialized. This method adds to whatever is already + // there, which can be useful when merging with multiple things. + QPDF_DLL + void mergeResources( + QPDFObjectHandle other, + std::map>* conflicts = nullptr); + + // Get all resource names from a resource dictionary. If this object is a dictionary, this + // method returns a set of all the keys in all top-level subdictionaries. For resources + // dictionaries, this is the collection of names that may be referenced in the content stream. + QPDF_DLL + std::set getResourceNames() const; + + // Find a unique name within a resource dictionary starting with a given prefix. This method + // works by appending a number to the given prefix. It searches starting with min_suffix and + // sets min_suffix to selected value upon return. This can be used to increase efficiency if + // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next + // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling + // this multiple times on the same resource dictionary, you can initialize resource_names by + // calling getResourceNames(), incrementally update it as you add resources, and keep passing it + // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time + // it's called. + QPDF_DLL + std::string getUniqueResourceName( + std::string const& prefix, + int& min_suffix, + std::set* resource_names = nullptr) const; + + // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF + // object. Indirect objects always have an owning QPDF. Direct objects that are read from the + // input source will also have an owning QPDF. Programmatically created objects will only have + // one if setObjectDescription was called. + // + // When the QPDF object that owns an object is destroyed, the object is changed into a null, and + // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the + // life of the QPDF. If in doubt, ask for it each time you need it. + + // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it + // returns a null pointer. Use this when you are able to handle the case of an object that + // doesn't have an owning QPDF. + QPDF_DLL + QPDF* getOwningQPDF() const; + // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a + // runtime_error. Use this when you know the object has to have an owning QPDF, such as when + // it's a known indirect object. Since streams are always indirect objects, this method can be + // used safely for streams. If error_msg is specified, it will be used at the contents of the + // runtime_error if there is now owner. + QPDF_DLL + QPDF& getQPDF(std::string const& error_msg = "") const; + + // Create a shallow copy of an object as a direct object, but do not traverse across indirect + // object boundaries. That means that, for dictionaries and arrays, any keys or items that were + // indirect objects will still be indirect objects that point to the same place. In the + // strictest sense, this is not a shallow copy because it recursively descends arrays and + // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You + // can't copy a stream this way. See copyStream() instead. + QPDF_DLL + QPDFObjectHandle shallowCopy(); + + // Create a true shallow copy of an array or dictionary, just copying the immediate items + // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in + // the copy, you are modifying the original, which is almost never what you want. However, if + // your intention is merely to *replace* top-level items or keys and not to modify lower-level + // items in the copy, this method is much faster than shallowCopy(). + QPDF_DLL + QPDFObjectHandle unsafeShallowCopy(); + + // Create a copy of this stream. The new stream and the old stream are independent: after the + // copy, either the original or the copy's dictionary or data can be modified without affecting + // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's + // data are made. If the source stream's data is already being provided by a StreamDataProvider, + // the new stream will use the same one, so you have to make sure your StreamDataProvider can + // handle that case. But if you're already using a StreamDataProvider, you probably don't need + // to call this method. + QPDF_DLL + QPDFObjectHandle copyStream(); + + // Mutator methods. + + // Since qpdf 11: for mutators that may add or remove an item, there are additional versions + // whose names contain "AndGet" that return the added or removed item. For example: + // + // auto new_dict = dict.replaceKeyAndGetNew( + // "/New", QPDFObjectHandle::newDictionary()); + // + // auto old_value = dict.replaceKeyAndGetOld( + // "/New", "(something)"_qpdf); + + // Recursively copy this object, making it direct. An exception is thrown if a loop is detected. + // With allow_streams true, keep indirect object references to streams. Otherwise, throw an + // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream + // is found, the resulting object is still associated with the containing qpdf. When + // allow_streams is false, the object will no longer be connected to the original QPDF object + // after this call completes successfully. + QPDF_DLL + void makeDirect(bool allow_streams = false); + + // Mutator methods for array objects + QPDF_DLL + void setArrayItem(int, QPDFObjectHandle const&); + QPDF_DLL + void setArrayFromVector(std::vector const& items); + // Insert an item before the item at the given position ("at") so that it has that position + // after insertion. If "at" is equal to the size of the array, insert the item at the end. + QPDF_DLL + void insertItem(int at, QPDFObjectHandle const& item); + // Like insertItem but return the item that was inserted. + QPDF_DLL + QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item); + // Append an item to an array. + QPDF_DLL + void appendItem(QPDFObjectHandle const& item); + // Append an item, and return the newly added item. + QPDF_DLL + QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item); + // Remove the item at that position, reducing the size of the array by one. + QPDF_DLL + void eraseItem(int at); + // Erase and item and return the item that was removed. + QPDF_DLL + QPDFObjectHandle eraseItemAndGetOld(int at); + + // Mutator methods for dictionary objects + + // Replace value of key, adding it if it does not exist. If value is null, remove the key. + QPDF_DLL + void replaceKey(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the value. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the old value, or null if the key was previously not present. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value); + // Remove key, doing nothing if key does not exist. + QPDF_DLL + void removeKey(std::string const& key); + // Remove key and return the old value. If the old value didn't exist, return a null object. + QPDF_DLL + QPDFObjectHandle removeKeyAndGetOld(std::string const& key); + + // Methods for stream objects + QPDF_DLL + QPDFObjectHandle getDict() const; + + // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode + // level, whether compression is enabled, and its ability to filter. Passing false will prevent + // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding + // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and + // recompressing a stream that it knows how to operate on for any application-specific reason, + // such as that you have already optimized its filtering. Note that this doesn't affect any + // other ways to get the stream's data, such as pipeStreamData or getStreamData. + QPDF_DLL + void setFilterOnWrite(bool); + QPDF_DLL + bool getFilterOnWrite(); + + // If addTokenFilter has been called for this stream, then the original data should be + // considered to be modified. This means we should avoid optimizations such as not filtering a + // stream that is already compressed. + QPDF_DLL + bool isDataModified(); + + // Returns filtered (uncompressed) stream data. Throws an exception if the stream is filtered + // and we can't decode it. + QPDF_DLL + std::shared_ptr getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized); + + // Returns unfiltered (raw) stream data. + QPDF_DLL + std::shared_ptr getRawStreamData(); + + // Write stream data through the given pipeline. A null pipeline value may be used if all you + // want to do is determine whether a stream is filterable and would be filtered based on the + // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags + // alter the behavior in the following way: + // + // encode_flags: + // + // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are + // applied. + // + // qpdf_sf_normalize -- tokenize as content stream and normalize tokens + // + // decode_level: + // + // qpdf_dl_none -- do not decode any streams. + // + // qpdf_dl_generalized -- decode supported general-purpose filters. This includes + // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode. + // + // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy + // specialized filters. This includes /RunLengthDecode. + // + // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported + // lossy filters. This includes /DCTDecode. + // + // If, based on the flags and the filters and decode parameters, we determine that we know how + // to apply all requested filters, do so and return true if we are successful. + // + // The exact meaning of the return value differs the different versions of this function, but + // for any version, the meaning has been the same. For the main version, added in qpdf 10, the + // return value indicates whether the overall operation succeeded. The filter parameter, if + // specified, will be set to whether or not filtering was attempted. If filtering was not + // requested, this value will be false even if the overall operation succeeded. + // + // If filtering is requested but this method returns false, it means there was some error in the + // filtering, in which case the resulting data is likely partially filtered and/or incomplete + // and may not be consistent with the configured filters. QPDFWriter handles this by attempting + // to get the stream data without filtering, but callers should consider a false return value + // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry + // in that case, pass true as the value of will_retry. This changes the warning issued by the + // library to indicate that the operation will be retried without filtering to avoid data loss. + + // Return value is overall success, even if filtering is not requested. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + bool* filtering_attempted, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy version. Return value is whether filtering was attempted. There is no way to determine + // success if filtering was not attempted. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows: + // filter = false -> encode_flags = 0 + // filter = true -> decode_level = qpdf_dl_generalized + // normalize = true -> encode_flags |= qpdf_sf_normalize + // compress = true -> encode_flags |= qpdf_sf_compress + // Return value is whether filtering was attempted. + QPDF_DLL + bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress); + + // Replace a stream's dictionary. The new dictionary must be consistent with the stream's data. + // This is most appropriately used when creating streams from scratch that will use a stream + // data provider and therefore start with an empty dictionary. It may be more convenient in + // this case than calling getDict and modifying it for each key. The pdf-create example does + // this. + QPDF_DLL + void replaceDict(QPDFObjectHandle const&); + + // Test whether a stream is the root XMP /Metadata object of its owning QPDF. + QPDF_DLL + bool isRootMetadata() const; + + // REPLACING STREAM DATA + + // Note about all replaceStreamData methods: whatever values are passed as filter and + // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object + // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf + // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing + // values untouched. + + // Replace this stream's stream data with the given data buffer. The stream's /Length key is + // replaced with the length of the data buffer. The stream is interpreted as if the data read + // from the file, after any decryption filters have been applied, is as presented. + QPDF_DLL + void replaceStreamData( + std::shared_ptr data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Replace the stream's stream data with the given string. This method will create a copy of the + // data rather than using the user-provided buffer as in the std::shared_ptr version of + // replaceStreamData. + QPDF_DLL + void replaceStreamData( + std::string const& data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // As above, replace this stream's stream data. Instead of directly providing a buffer with the + // stream data, call the given provider's provideStreamData method. See comments on the + // StreamDataProvider class (defined above) for details on the method. The data must be + // consistent with filter and decode_parms as provided. Although it is more complex to use this + // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid + // allocating memory for the stream data. Example programs are provided that use both forms of + // replaceStreamData. + + // Note about stream length: for any given stream, the provider must provide the same amount of + // data each time it is called. This is critical for making linearization work properly. + // Versions of qpdf before 3.0.0 required a length to be specified here. Starting with + // version 3.0.0, this is no longer necessary (or permitted). The first time the stream data + // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is + // enforced that the length be the same as the first time. + + // If you have gotten a compile error here while building code that worked with older versions + // of qpdf, just omit the length parameter. You can also simplify your code by not having to + // compute the length in advance. + QPDF_DLL + void replaceStreamData( + std::shared_ptr provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider. + + // The provider should write the stream data to the pipeline. For a one-liner to replace stream + // data with the contents of a file, pass QUtil::file_provider(filename) as provider. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + // The provider should write the stream data to the pipeline, returning true if it succeeded + // without errors. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Access object ID and generation. For direct objects, return object ID 0. + + // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to + // the pattern of depending on object ID or generation without the other. In general, when + // keeping track of object IDs, it's better to use QPDFObjGen instead. + + QPDF_DLL + QPDFObjGen getObjGen() const; + QPDF_DLL + int getObjectID() const; + QPDF_DLL + int getGeneration() const; + + QPDF_DLL + std::string unparse() const; + QPDF_DLL + std::string unparseResolved() const; + // For strings only, force binary representation. Otherwise, same as unparse. + QPDF_DLL + std::string unparseBinary() const; + + // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available + // JSON version. The JSON is generated as follows: + // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their + // native JSON types. + // * Names are encoded as strings representing the canonical representation (after parsing #xx) + // and preceded by a slash, just as unparse() returns. For example, the JSON for the + // PDF-syntax name /Text#2fPlain would be "/Text/Plain". + // * Indirect references are encoded as strings containing "obj gen R" + // * Strings + // * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters + // encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode + // mappings are not reversible. There is no way to tell the difference between a string that + // looks like a name or indirect object from an actual name or indirect object. + // * JSON v2: + // * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally + // mapped to Unicode (which is all strings without undefined characters) are represented + // as "u:" followed by the UTF-8 encoded string. Example: + // "u:potato". + // * All other strings are represented as "b:" followed by a hexadecimal encoding of the + // string. Example: "b:0102cacb" + // * Streams + // * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a + // dictionary other than context. + // * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the + // stream's dictionary. Since "dict" does not otherwise represent anything, this is + // unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data. + // * Object types that are only valid in content streams (inline image, operator) are serialized + // as "null". Attempting to serialize a "reserved" object is an error. + // If dereference_indirect is true and this is an indirect object, show the actual contents of + // the object. The effect of dereference_indirect applies only to this object. It is not + // recursive. + QPDF_DLL + JSON getJSON(int json_version, bool dereference_indirect = false) const; + + // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient + // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the + // documentation for getJSON and JSON::write for further detail. + QPDF_DLL + void writeJSON( + int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const; + + // This method can be called on a stream to get a more extended JSON representation of the + // stream that includes the stream's data. The JSON object returned is always a dictionary whose + // "dict" key is an encoding of the stream's dictionary. The representation of the data is + // determined by the json_data field. + // + // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file. + // + // If json_data is qpdf_sj_none, stream data is not represented. + // + // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on + // the value of decode_level, which has the same meaning as with pipeStreamData. + // + // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data" + // field of the dictionary that is returned. + // + // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be + // supplied. The value of data_filename is stored in the resulting json in the "datafile" key + // but is not otherwise use. The stream data itself (raw or filtered depending on decode level), + // is written to the pipeline via pipeStreamData(). + // + // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must + // remain valid until after the JSON object is written. + QPDF_DLL + JSON getStreamJSON( + int json_version, + qpdf_json_stream_data_e json_data, + qpdf_stream_decode_level_e decode_level, + Pipeline* p, + std::string const& data_filename); + + // Legacy helper methods for commonly performed operations on pages. Newer code should use + // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as + // the identically named methods in that class, but newer functionality will be added there. + QPDF_DLL + std::map getPageImages(); + QPDF_DLL + std::vector getPageContents(); + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + QPDF_DLL + void rotatePage(int angle, bool relative); + QPDF_DLL + void coalesceContentStreams(); + // End legacy page helpers + + // Issue a warning about this object if possible. If the object has a description, a warning + // will be issued using the owning QPDF as context. Otherwise, a message will be written to the + // default logger's error stream, which is standard error if not overridden. Objects read + // normally from the file have descriptions. See comments on setObjectDescription for additional + // details. + QPDF_DLL + void warnIfPossible(std::string const& warning) const; + + // Convenience routine: Throws if the assumption is violated. Your code will be better if you + // call one of the isType methods and handle the case of the type being wrong, but these can be + // convenient if you have already verified the type. + QPDF_DLL + void assertInitialized() const; + + QPDF_DLL + void assertNull() const; + QPDF_DLL + void assertBool() const; + QPDF_DLL + void assertInteger() const; + QPDF_DLL + void assertReal() const; + QPDF_DLL + void assertName() const; + QPDF_DLL + void assertString() const; + QPDF_DLL + void assertOperator() const; + QPDF_DLL + void assertInlineImage() const; + QPDF_DLL + void assertArray() const; + QPDF_DLL + void assertDictionary() const; + QPDF_DLL + void assertStream() const; + QPDF_DLL + void assertReserved() const; + + QPDF_DLL + void assertIndirect() const; + QPDF_DLL + void assertScalar() const; + QPDF_DLL + void assertNumber() const; + + // The isPageObject method checks the /Type key of the object. This is not completely reliable + // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is + // slightly more accepting but may still return false here when treating the object as a page + // would work. Use this sparingly. + QPDF_DLL + bool isPageObject() const; + QPDF_DLL + bool isPagesObject() const; + QPDF_DLL + void assertPageObject() const; + + QPDF_DLL + bool isFormXObject() const; + + // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as + // images. + QPDF_DLL + bool isImage(bool exclude_imagemask = true) const; + + // The following methods do not form part of the public API and are for internal use only. + + QPDFObjectHandle(std::shared_ptr const& obj) : + qpdf::BaseHandle(obj) + { + } + QPDFObjectHandle(std::shared_ptr&& obj) : + qpdf::BaseHandle(std::move(obj)) + { + } + std::shared_ptr + getObj() + { + return obj; + } + + void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const; + + inline qpdf::Array as_array(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Dictionary as_dictionary(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const; + + private: + void typeWarning(char const* expected_type, std::string const& warning) const; + void objectWarning(std::string const& warning) const; + void assertType(char const* type_name, bool istype) const; + void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); + void setParsedOffset(qpdf_offset_t offset); + void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); + static void parseContentStream_data( + std::string_view stream_data, + std::string const& description, + ParserCallbacks* callbacks, + QPDF* context); + std::vector + arrayOrStreamToStreamArray(std::string const& description, std::string& all_description); + void checkOwnership(QPDFObjectHandle const&) const; +}; + +#ifndef QPDF_NO_QPDF_STRING +// This is short for QPDFObjectHandle::parse, so you can do + +// auto oh = "<< /Key (value) >>"_qpdf; + +// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration +// from being here. + +/* clang-format off */ + // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest + // of the file as a string if clang-format removes the space after "operator", and as of + // clang-format 15, there's no way to prevent it from doing so. + QPDF_DLL + QPDFObjectHandle operator ""_qpdf(char const* v, size_t len); +/* clang-format on */ + +#endif // QPDF_NO_QPDF_STRING + +class QPDFObjectHandle::QPDFDictItems +{ + // This class allows C++-style iteration, including range-for iteration, around dictionaries. + // You can write + + // for (auto iter: QPDFDictItems(dictionary_obj)) + // { + // // iter.first is a string + // // iter.second is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFDictItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFDictItems; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFDictItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + std::set keys; + std::set::iterator iter; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +class QPDFObjectHandle::QPDFArrayItems +{ + // This class allows C++-style iteration, including range-for iteration, around arrays. You can + // write + + // for (auto iter: QPDFArrayItems(array_obj)) + // { + // // iter is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFArrayItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFArrayItems; + + public: + typedef QPDFObjectHandle T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFArrayItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + int item_number; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +namespace qpdf +{ + inline BaseHandle:: + operator bool() const + { + return static_cast(obj); + } + + inline BaseHandle:: + operator QPDFObjectHandle() const + { + return {obj}; + } + +} // namespace qpdf + +inline bool +QPDFObjectHandle::isInitialized() const +{ + return obj != nullptr; +} + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjectHelper.hh new file mode 100644 index 0000000..d19ba3b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFObjectHelper.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJECTHELPER_HH +#define QPDFOBJECTHELPER_HH + +#include + +#include + +// This is a base class for QPDF Object Helper classes. Object helpers are classes that provide a +// convenient, higher-level API for working with specific types of QPDF objects. Object helpers are +// always initialized with a QPDFObjectHandle, and the underlying object handle can always be +// retrieved. The intention is that you may freely intermix use of object helpers with the +// underlying QPDF objects unless there is a specific comment in a specific helper method that says +// otherwise. The pattern of using helper objects was introduced to allow creation of higher level +// helper functions without polluting the public interface of QPDFObjectHandle. +class QPDF_DLL_CLASS QPDFObjectHelper: public qpdf::BaseHandle +{ + public: + QPDFObjectHelper(QPDFObjectHandle oh) : + qpdf::BaseHandle(oh.getObj()) + { + } + QPDF_DLL + virtual ~QPDFObjectHelper(); + QPDFObjectHandle + getObjectHandle() + { + return {obj}; + } + QPDFObjectHandle const + getObjectHandle() const + { + return {obj}; + } + + protected: + QPDF_DLL_PRIVATE + QPDFObjectHandle + oh() + { + return {obj}; + } + QPDF_DLL_PRIVATE + QPDFObjectHandle const + oh() const + { + return {obj}; + } + QPDFObjectHandle oh_; +}; + +#endif // QPDFOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFOutlineDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFOutlineDocumentHelper.hh new file mode 100644 index 0000000..66b4481 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFOutlineDocumentHelper.hh @@ -0,0 +1,92 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEDOCUMENTHELPER_HH +#define QPDFOUTLINEDOCUMENTHELPER_HH + +#include +#include +#include +#include +#include + +#include +#include + +#include + +// This is a document helper for outlines, also known as bookmarks. Outlines are discussed in +// section 12.3.3 of the PDF spec (ISO-32000). With the help of QPDFOutlineObjectHelper, the +// outlines tree is traversed, and a bidirectional map is made between pages and outlines. See also +// QPDFOutlineObjectHelper. +class QPDFOutlineDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFOutlineDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Outlines structure. This is useful if you have modified the structure of the + // Outlines dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFOutlineDocumentHelper(QPDF&); + + ~QPDFOutlineDocumentHelper() override = default; + + QPDF_DLL + bool hasOutlines(); + + QPDF_DLL + std::vector getTopLevelOutlines(); + + // If the name is a name object, look it up in the /Dests key of the document catalog. If the + // name is a string, look it up in the name tree pointed to by the /Dests key of the names + // dictionary. + QPDF_DLL + QPDFObjectHandle resolveNamedDest(QPDFObjectHandle name); + + // Return a list outlines that are known to target the specified page. + QPDF_DLL + std::vector getOutlinesForPage(QPDFObjGen); + + class Accessor + { + friend class QPDFOutlineObjectHelper; + + static bool checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen og); + }; + + private: + void initializeByPage(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFOutlineObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFOutlineObjectHelper.hh new file mode 100644 index 0000000..108ec59 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFOutlineObjectHelper.hh @@ -0,0 +1,109 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEOBJECTHELPER_HH +#define QPDFOUTLINEOBJECTHELPER_HH + +#include +#include +#include + +class QPDFOutlineDocumentHelper; + +#include + +// This is an object helper for outline items. Outlines, also known as bookmarks, are described in +// section 12.3.3 of the PDF spec (ISO-32000). See comments below for details. +class QPDFOutlineObjectHelper: public QPDFObjectHelper +{ + public: + ~QPDFOutlineObjectHelper() override + { + // This must be cleared explicitly to avoid circular references that prevent cleanup of + // shared pointers. + m->parent = nullptr; + } + + // All constructors are private. You can only create one of these using + // QPDFOutlineDocumentHelper. + + // Return parent pointer. Returns a null pointer if this is a top-level outline. + QPDF_DLL + std::shared_ptr getParent(); + + // Return children as a list. + QPDF_DLL + std::vector getKids(); + + // Return the destination, regardless of whether it is named or explicit and whether it is + // directly provided or in a GoTo action. Returns a null object if the destination can't be + // determined. Named destinations can be resolved using the older root /Dest dictionary or the + // current names tree. + QPDF_DLL + QPDFObjectHandle getDest(); + + // Return the page that the outline points to. Returns a null object if the destination page + // can't be determined. + QPDF_DLL + QPDFObjectHandle getDestPage(); + + // Returns the value of /Count as present in the object, or 0 if not present. If count is + // positive, the outline is open. If negative, it is closed. Either way, the absolute value is + // the number of descendant items that would be visible if this were open. + QPDF_DLL + int getCount(); + + // Returns the title as a UTF-8 string. Returns an empty string if there is no title. + QPDF_DLL + std::string getTitle(); + + class Accessor + { + friend class QPDFOutlineDocumentHelper; + + static QPDFOutlineObjectHelper + create(QPDFObjectHandle oh, QPDFOutlineDocumentHelper& dh, int depth) + { + return {oh, dh, depth}; + } + }; + + private: + QPDFOutlineObjectHelper(QPDFObjectHandle, QPDFOutlineDocumentHelper&, int); + + class Members + { + friend class QPDFOutlineObjectHelper; + + public: + ~Members() = default; + + private: + Members(QPDFOutlineDocumentHelper& dh); + Members(Members const&) = delete; + + QPDFOutlineDocumentHelper& dh; + std::shared_ptr parent; + std::vector kids; + }; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageDocumentHelper.hh new file mode 100644 index 0000000..a2cd9f8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageDocumentHelper.hh @@ -0,0 +1,128 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEDOCUMENTHELPER_HH +#define QPDFPAGEDOCUMENTHELPER_HH + +#include +#include +#include + +#include + +#include + +#include + +class QPDFAcroFormDocumentHelper; + +class QPDFPageDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFPageDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Pages structure. This is useful if you have modified the Pages structure in + // a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageDocumentHelper(QPDF&); + + ~QPDFPageDocumentHelper() override = default; + + // Traverse page tree, and return all /Page objects wrapped in QPDFPageObjectHelper objects. + // Unlike with QPDF::getAllPages, the vector of pages returned by this call is not affected by + // additions or removals of pages. If you manipulate pages, you will have to call this again to + // get a new copy. Please see comments in QPDF.hh for getAllPages() for additional details. + QPDF_DLL + std::vector getAllPages(); + + // The PDF /Pages tree allows inherited values. Working with the pages of a pdf is much easier + // when the inheritance is resolved by explicitly setting the values in each /Page. + QPDF_DLL + void pushInheritedAttributesToPage(); + + // This calls QPDFPageObjectHelper::removeUnreferencedResources for every page in the document. + // See comments in QPDFPageObjectHelper.hh for details. + QPDF_DLL + void removeUnreferencedResources(); + + // Add a new page at the beginning or the end of the current pdf. The newpage parameter may be + // either a direct object, an indirect object from this QPDF, or an indirect object from another + // QPDF. If it is a direct object, it will be made indirect. If it is an indirect object from + // another QPDF, this method will call pushInheritedAttributesToPage on the other file and then + // copy the page to this QPDF using the same underlying code as copyForeignObject. At this + // stage, if the indirect object is already in the pages tree, a shallow copy is made to avoid + // adding the same page more than once. In version 10.3.1 and earlier, adding a page that + // already existed would throw an exception and could cause qpdf to crash on subsequent page + // insertions in some cases. Note that this means that, in some cases, the page actually added + // won't be exactly the same object as the one passed in. If you want to do subsequent + // modification on the page, you should retrieve it again. + // + // Note that you can call copyForeignObject directly to copy a page from a different file, but + // the resulting object will not be a page in the new file. You could do this, for example, to + // convert a page into a form XObject, though for that, you're better off using + // QPDFPageObjectHelper::getFormXObjectForPage. + // + // This method does not have any specific awareness of annotations or form fields, so if you + // just add a page without thinking about it, you might end up with two pages that share form + // fields or annotations. While the page may look fine, it will probably not function properly + // with regard to interactive features. To work around this, you should call + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations. A future version of qpdf will likely + // provide a higher-level interface for copying pages around that will handle document-level + // constructs in a less error-prone fashion. + + QPDF_DLL + void addPage(QPDFPageObjectHelper newpage, bool first); + + // Add new page before or after refpage. See comments for addPage for details about what newpage + // should be. + QPDF_DLL + void addPageAt(QPDFPageObjectHelper newpage, bool before, QPDFPageObjectHelper refpage); + + // Remove page from the pdf. + QPDF_DLL + void removePage(QPDFPageObjectHelper page); + + // For every annotation, integrate the annotation's appearance stream into the containing page's + // content streams, merge the annotation's resources with the page's resources, and remove the + // annotation from the page. Handles widget annotations associated with interactive form fields + // as a special case, including removing the /AcroForm key from the document catalog. The values + // passed to required_flags and forbidden_flags are passed along to + // QPDFAnnotationObjectHelper::getPageContentForAppearance. See comments there in + // QPDFAnnotationObjectHelper.hh for meanings of those flags. + QPDF_DLL + void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageLabelDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageLabelDocumentHelper.hh new file mode 100644 index 0000000..51e2265 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageLabelDocumentHelper.hh @@ -0,0 +1,99 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGELABELDOCUMENTHELPER_HH +#define QPDFPAGELABELDOCUMENTHELPER_HH + +#include + +#include +#include + +#include + +// Page labels are discussed in the PDF spec (ISO-32000) in section 12.4.2. +// +// Page labels are implemented as a number tree. Each key is a page index, numbered from 0. The +// values are dictionaries with the following keys, all optional: +// +// * /Type: if present, must be /PageLabel +// * /S: one of /D, /R, /r, /A, or /a for decimal, upper-case and lower-case Roman numeral, or +// upper-case and lower-case alphabetic +// * /P: if present, a fixed prefix string that is prepended to each page number +// * /St: the starting number, or 1 if not specified + +class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the PageLabels structure, which can be expensive. + QPDF_DLL + static QPDFPageLabelDocumentHelper& get(QPDF& qpdf); + + // Re-validate the PageLabels structure. This is useful if you have modified the structure of + // the PageLabels dictionary in a way that could have invalidated the structure. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageLabelDocumentHelper(QPDF&); + + ~QPDFPageLabelDocumentHelper() override = default; + + QPDF_DLL + bool hasPageLabels(); + + // Helper function to create a dictionary suitable for adding to the /PageLabels numbers tree. + QPDF_DLL + static QPDFObjectHandle + pageLabelDict(qpdf_page_label_e label_type, int start_num, std::string_view prefix); + + // Return a page label dictionary representing the page label for the given page. The page does + // not need to appear explicitly in the page label dictionary. This method will adjust /St as + // needed to produce a label that is suitable for the page. + QPDF_DLL + QPDFObjectHandle getLabelForPage(long long page_idx); + + // Append to the incoming vector a list of objects suitable for inclusion in a /PageLabels + // dictionary's /Nums field. start_idx and end_idx are the indexes to the starting and ending + // pages (inclusive) in the original file, and new_start_idx is the index to the first page in + // the new file. For example, if pages 10 through 12 of one file are being copied to a new file + // as pages 6 through 8, you would call getLabelsForPageRange(10, 12, 6), which would return as + // many entries as are required to add to the new file's PageLabels. This method fabricates a + // suitable entry even if the original document has no page labels. This behavior facilitates + // using this function to incrementally build up a page labels tree when merging files. + QPDF_DLL + void getLabelsForPageRange( + long long start_idx, + long long end_idx, + long long new_start_idx, + std::vector& new_labels); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGELABELDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageObjectHelper.hh new file mode 100644 index 0000000..ef8346e --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFPageObjectHelper.hh @@ -0,0 +1,423 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEOBJECTHELPER_HH +#define QPDFPAGEOBJECTHELPER_HH + +#include +#include +#include + +#include + +#include +#include + +class QPDFAcroFormDocumentHelper; + +// This is a helper class for page objects, but as of qpdf 10.1, many of the methods also work +// for form XObjects. When this is the case, it is noted in the comment. +class QPDFPageObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFPageObjectHelper(QPDFObjectHandle); + + ~QPDFPageObjectHelper() override = default; + + // PAGE ATTRIBUTES + + // The getAttribute method works with pages and form XObjects. It returns the value of the + // requested attribute from the page/form XObject's dictionary, taking inheritance from the + // pages tree into consideration. For pages, the attributes /MediaBox, /CropBox, /Resources, and + // /Rotate are inheritable, meaning that if they are not present directly on the page node, they + // may be inherited from ancestor nodes in the pages tree. + // + // There are two ways that an attribute can be "shared": + // + // * For inheritable attributes on pages, it may appear in a higher level node of the pages tree + // + // * For any attribute, the attribute may be an indirect object which may be referenced by more + // than one page/form XObject. + // + // If copy_if_shared is true, then this method will replace the attribute with a shallow copy if + // it is indirect or inherited and return the copy. You should do this if you are going to + // modify the returned object and want the modifications to apply to the current page/form + // XObject only. + QPDF_DLL + QPDFObjectHandle getAttribute(std::string const& name, bool copy_if_shared); + + // PAGE BOXES + // + // Pages have various types of boundary boxes. These are described in detail in the PDF + // specification (section 14.11.2 Page boundaries). They are, by key in the page dictionary: + // + // * /MediaBox -- boundaries of physical page + // * /CropBox -- clipping region of what is displayed + // * /BleedBox -- clipping region for production environments + // * /TrimBox -- dimensions of final printed page after trimming + // * /ArtBox -- extent of meaningful content including margins + // + // Of these, only /MediaBox is required. If any are absent, the + // fallback value for /CropBox is /MediaBox, and the fallback + // values for the other boxes are /CropBox. + // + // As noted above (PAGE ATTRIBUTES), /MediaBox and /CropBox can be inherited from parent nodes + // in the pages tree. The other boxes can't be inherited. + // + // When the comments below refer to the "effective value" of a box, this takes into + // consideration both inheritance through the pages tree (in the case of /MediaBox and /CropBox) + // and fallback values for missing attributes (for all except /MediaBox). + // + // For the methods below, copy_if_shared is passed to getAttribute and therefore refers only to + // indirect objects and values that are inherited through the pages tree. + // + // If copy_if_fallback is true, a copy is made if the object's value was obtained by falling + // back to a different box. + // + // The copy_if_shared and copy_if_fallback parameters carry across multiple layers. This is + // explained below. + // + // You should set copy_if_shared to true if you want to modify a bounding box for the current + // page without affecting other pages but you don't want to change the fallback behavior. For + // example, if you want to modify the /TrimBox for the current page only but have it continue to + // fall back to the value of /CropBox or /MediaBox if they are not defined, you could set + // copy_if_shared to true. + // + // You should set copy_if_fallback to true if you want to modify a specific box as distinct from + // any other box. For example, if you want to make /TrimBox differ from /CropBox, then you + // should set copy_if_fallback to true. + // + // The copy_if_fallback flags were added in qpdf 11. + // + // For example, suppose that neither /CropBox nor /TrimBox is present on a page but /CropBox is + // present in the page's parent node in the page tree. + // + // * getTrimBox(false, false) would return the /CropBox from the parent node. + // + // * getTrimBox(true, false) would make a shallow copy of the /CropBox from the parent node into + // the current node and return it. + // + // * getTrimBox(false, true) would make a shallow copy of the /CropBox from the parent node into + // /TrimBox of the current node and return it. + // + // * getTrimBox(true, true) would make a shallow copy of the /CropBox from the parent node into + // the current node, then make a shallow copy of the resulting copy to /TrimBox of the current + // node, and then return that. + // + // To illustrate how these parameters carry across multiple layers, suppose that neither + // /MediaBox, /CropBox, nor /TrimBox is present on a page but /MediaBox is present on the + // parent. In this case: + // + // * getTrimBox(false, false) would return the value of /MediaBox from the parent node. + // + // * getTrimBox(true, false) would copy /MediaBox to the current node and return it. + // + // * getTrimBox(false, true) would first copy /MediaBox from the parent to /CropBox, then copy + // /CropBox to /TrimBox, and then return the result. + // + // * getTrimBox(true, true) would first copy /MediaBox from the parent to the current page, then + // copy it to /CropBox, then copy /CropBox to /TrimBox, and then return the result. + // + // If you need different behavior, call getAttribute directly and take care of your own copying. + + // Return the effective MediaBox + QPDF_DLL + QPDFObjectHandle getMediaBox(bool copy_if_shared = false); + + // Return the effective CropBox. If not defined, fall back to MediaBox + QPDF_DLL + QPDFObjectHandle getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective BleedBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective TrimBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective ArtBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Iterate through XObjects, possibly recursing into form XObjects. This works with pages or + // form XObjects. Call action on each XObject for which selector, if specified, returns true. + // With no selector, calls action for every object. In addition to the object being passed to + // action, the containing XObject dictionary and key are passed in. Remember that the XObject + // dictionary may be shared, and the object may appear in multiple XObject dictionaries. + QPDF_DLL + void forEachXObject( + bool recursive, + std::function action, + std::function selector = nullptr); + // Only call action for images + QPDF_DLL + void forEachImage( + bool recursive, + std::function action); + // Only call action for form XObjects + QPDF_DLL + void forEachFormXObject( + bool recursive, + std::function action); + + // Returns an empty map if there are no images or no resources. Prior to qpdf 8.4.0, this + // function did not support inherited resources, but it does now. Return value is a map from + // XObject name to the image object, which is always a stream. Works with form XObjects as well + // as pages. This method does not recurse into nested form XObjects. For that, use forEachImage. + QPDF_DLL + std::map getImages(); + + // Old name -- calls getImages() + QPDF_DLL + std::map getPageImages(); + + // Returns an empty map if there are no form XObjects or no resources. Otherwise, returns a map + // of keys to form XObjects directly referenced from this page or form XObjects. This does not + // recurse into nested form XObjects. For that, use forEachFormXObject. + QPDF_DLL + std::map getFormXObjects(); + + // Converts each inline image to an external (normal) image if the size is at least the + // specified number of bytes. This method works with pages or form XObjects. By default, it + // recursively processes nested form XObjects. Pass true as shallow to avoid this behavior. + // Prior to qpdf 10.1, form XObjects were ignored, but this was considered a bug. + QPDF_DLL + void externalizeInlineImages(size_t min_size = 0, bool shallow = false); + + // Return the annotations in the page's "/Annots" list, if any. If only_subtype is non-empty, + // only include annotations of the given subtype. + QPDF_DLL + std::vector getAnnotations(std::string const& only_subtype = ""); + + // Returns a vector of stream objects representing the content streams for the given page. This + // routine allows the caller to not care whether there are one or more than one content streams + // for a page. + QPDF_DLL + std::vector getPageContents(); + + // Add the given object as a new content stream for this page. If parameter 'first' is true, add + // to the beginning. Otherwise, add to the end. This routine automatically converts the page + // contents to an array if it is a scalar, allowing the caller not to care what the initial + // structure is. You can call coalesceContentStreams() afterwards if you want to force it to be + // a single stream. + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + + // Rotate a page. If relative is false, set the rotation of the page to angle. Otherwise, add + // angle to the rotation of the page. Angle must be a multiple of 90. Adding 90 to the rotation + // rotates clockwise by 90 degrees. + QPDF_DLL + void rotatePage(int angle, bool relative); + + // Coalesce a page's content streams. A page's content may be a stream or an array of streams. + // If this page's content is an array, concatenate the streams into a single stream. This can be + // useful when working with files that split content streams in arbitrary spots, such as in the + // middle of a token, as that can confuse some software. You could also call this after calling + // addPageContents. + QPDF_DLL + void coalesceContentStreams(); + + // + // Content stream handling + // + + // Parse a page's contents through ParserCallbacks, described above. This method works whether + // the contents are a single stream or an array of streams. Call on a page object. Also works + // for form XObjects. + QPDF_DLL + void parseContents(QPDFObjectHandle::ParserCallbacks* callbacks); + // Old name + QPDF_DLL + void parsePageContents(QPDFObjectHandle::ParserCallbacks* callbacks); + + // Pass a page's or form XObject's contents through the given TokenFilter. If a pipeline is also + // provided, it will be the target of the write methods from the token filter. If a pipeline is + // not specified, any output generated by the token filter will be discarded. Use this interface + // if you need to pass a page's contents through filter for work purposes without having that + // filter automatically applied to the page's contents, as happens with addContentTokenFilter. + // See examples/pdf-count-strings.cc for an example. + QPDF_DLL + void filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Old name -- calls filterContents() + QPDF_DLL + void filterPageContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Pipe a page's contents through the given pipeline. This method works whether the contents are + // a single stream or an array of streams. Also works on form XObjects. + QPDF_DLL + void pipeContents(Pipeline* p); + // Old name + QPDF_DLL + void pipePageContents(Pipeline* p); + + // Attach a token filter to a page's contents. If the page's contents is an array of streams, it + // is automatically coalesced. The token filter is applied to the page's contents as a single + // stream. Also works on form XObjects. + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + + // A page's resources dictionary maps names to objects elsewhere in the file. This method walks + // through a page's contents and keeps tracks of which resources are referenced somewhere in the + // contents. Then it removes from the resources dictionary any object that is not referenced in + // the contents. This operation is most useful after calling + // QPDFPageDocumentHelper::pushInheritedAttributesToPage(). This method is used by page + // splitting code to avoid copying unused objects in files that used shared resource + // dictionaries across multiple pages. This method recurses into form XObjects and can be called + // with a form XObject as well as a page. + QPDF_DLL + void removeUnreferencedResources(); + + // Return a new QPDFPageObjectHelper that is a duplicate of the page. The returned object is an + // indirect object that is ready to be inserted into the same or a different QPDF object using + // any of the addPage methods in QPDFPageDocumentHelper or QPDF. Without calling one of those + // methods, the page will not be added anywhere. The new page object shares all content streams + // and indirect object resources with the original page, so if you are going to modify the + // contents or other aspects of the page, you will need to handling copying of the component + // parts separately. + QPDF_DLL + QPDFPageObjectHelper shallowCopyPage(); + + // Return a transformation matrix whose effect is the same as the page's /Rotate and /UserUnit + // parameters. If invert is true, return a matrix whose effect is the opposite. The regular + // matrix is suitable for taking something from this page to put elsewhere, and the second one + // is suitable for putting something else onto this page. The page's TrimBox is used as the + // bounding box for purposes of computing the matrix. + QPDF_DLL + QPDFObjectHandle::Matrix getMatrixForTransformations(bool invert = false); + + // Return a form XObject that draws this page. This is useful for n-up operations, underlay, + // overlay, thumbnail generation, or any other case in which it is useful to replicate the + // contents of a page in some other context. The dictionaries are shallow copies of the original + // page dictionary, and the contents are coalesced from the page's contents. The resulting + // object handle is not referenced anywhere. If handle_transformations is true, the resulting + // form XObject's /Matrix will be set to replicate rotation (/Rotate) and scaling (/UserUnit) in + // the page's dictionary. In this way, the page's transformations will be preserved when placing + // this object on another page. + QPDF_DLL + QPDFObjectHandle getFormXObjectForPage(bool handle_transformations = true); + + // Return content stream text that will place the given form XObject (fo) using the resource + // name "name" on this page centered within the given rectangle. If invert_transformations is + // true, the effect of any rotation (/Rotate) and scaling (/UserUnit) applied to the current + // page will be inverted in the form XObject placement. This will cause the form XObject's + // absolute orientation to be preserved. You could overlay one page on another by calling + // getFormXObjectForPage on the original page, QPDFObjectHandle::getUniqueResourceName on the + // destination page's Resources dictionary to generate a name for the resulting object, and + // calling placeFormXObject on the destination page. Then insert the new fo (or, if it comes + // from a different file, the result of calling copyForeignObject on it) into the resources + // dictionary using name, and append or prepend the content to the page's content streams. See + // the overlay/underlay code in qpdf.cc or examples/pdf-overlay-page.cc for an example. From + // qpdf 10.0.0, the allow_shrink and allow_expand parameters control whether the form XObject is + // allowed to be shrunk or expanded to stay within or maximally fill the destination rectangle. + // The default values are for backward compatibility with the pre-10.0.0 behavior. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Alternative version that also fills in the transformation matrix that was used. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + QPDFMatrix& cm, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Return the transformation matrix that translates from the given form XObject's coordinate + // system into the given rectangular region on the page. The parameters have the same meaning as + // for placeFormXObject. + QPDF_DLL + QPDFMatrix getMatrixForFormXObjectPlacement( + QPDFObjectHandle fo, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // If a page is rotated using /Rotate in the page's dictionary, instead rotate the page by the + // same amount by altering the contents and removing the /Rotate key. This method adjusts the + // various page bounding boxes (/MediaBox, etc.) so that the page will have the same semantics. + // This can be useful to work around problems with PDF applications that can't properly handle + // rotated pages. If a QPDFAcroFormDocumentHelper is provided, it will be used for resolving any + // form fields that have to be rotated. If not, one will be created inside the function, which + // is less efficient. + QPDF_DLL + void flattenRotation(QPDFAcroFormDocumentHelper* afdh = nullptr); + + // Copy annotations from another page into this page. The other page may be from the same QPDF + // or from a different QPDF. Each annotation's rectangle is transformed by the given matrix. If + // the annotation is a widget annotation that is associated with a form field, the form field is + // copied into this document's AcroForm dictionary as well. You can use this to copy annotations + // from a page that was converted to a form XObject and added to another page. For example of + // this, see examples/pdf-overlay-page.cc. This method calls + // QPDFAcroFormDocumentHelper::transformAnnotations, which will copy annotations and form fields + // so that you can copy annotations from a source page to any number of other pages, even with + // different matrices, and maintain independence from the original annotations. See also + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations, which can be used if you copy a page and + // want to repair the annotations on the destination page to make them independent from the + // original page's annotations. + // + // If you pass in a QPDFAcroFormDocumentHelper*, the method will use that instead of creating + // one in the function. Creating QPDFAcroFormDocumentHelper objects is expensive, so if you're + // doing a lot of copying, it can be more efficient to create these outside and pass them in. + QPDF_DLL + void copyAnnotations( + QPDFPageObjectHelper from_page, + QPDFMatrix const& cm = QPDFMatrix(), + QPDFAcroFormDocumentHelper* afdh = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + private: + QPDFObjectHandle getAttribute( + std::string const& name, + bool copy_if_shared, + std::function get_fallback, + bool copy_if_fallback); + static bool + removeUnreferencedResourcesHelper(QPDFPageObjectHelper ph, std::set& unresolved); + + class Members + { + friend class QPDFPageObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFStreamFilter.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFStreamFilter.hh new file mode 100644 index 0000000..5cba242 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFStreamFilter.hh @@ -0,0 +1,67 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSTREAMFILTER_HH +#define QPDFSTREAMFILTER_HH + +#include +#include +#include + +class QPDF_DLL_CLASS QPDFStreamFilter +{ + public: + QPDFStreamFilter() = default; + + virtual ~QPDFStreamFilter() = default; + + // A QPDFStreamFilter class must implement, at a minimum, setDecodeParms() and + // getDecodePipeline(). QPDF will always call setDecodeParms() before calling + // getDecodePipeline(). It is expected that you will store any needed information from + // decode_parms (or the decode_parms object itself) in your instance so that it can be used to + // construct the decode pipeline. + + // Return a boolean indicating whether your filter can proceed with the given /DecodeParms. The + // default implementation accepts a null object and rejects everything else. + QPDF_DLL + virtual bool setDecodeParms(QPDFObjectHandle decode_parms); + + // Return a pipeline that will decode data encoded with your filter. Your implementation must + // ensure that the pipeline is deleted when the instance of your class is destroyed. + QPDF_DLL + virtual Pipeline* getDecodePipeline(Pipeline* next) = 0; + + // If your filter implements "specialized" compression or lossy compression, override one or + // both of these methods. The default implementations return false. See comments in QPDFWriter + // for details. QPDF defines specialized compression as non-lossy compression not intended for + // general-purpose data. qpdf, by default, doesn't mess with streams that are compressed with + // specialized compression, the idea being that the decision to use that compression scheme + // would fall outside of what QPDFWriter would know anything about, so any attempt to decode and + // re-encode would probably be undesirable. + QPDF_DLL + virtual bool isSpecializedCompression(); + QPDF_DLL + virtual bool isLossyCompression(); + + private: + QPDFStreamFilter(QPDFStreamFilter const&) = delete; + QPDFStreamFilter& operator=(QPDFStreamFilter const&) = delete; +}; + +#endif // QPDFSTREAMFILTER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFSystemError.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFSystemError.hh new file mode 100644 index 0000000..94e0ab0 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFSystemError.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSYSTEMERROR_HH +#define QPDFSYSTEMERROR_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error +{ + public: + QPDF_DLL + QPDFSystemError(std::string const& description, int system_errno); + + ~QPDFSystemError() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. + + QPDF_DLL + std::string const& getDescription() const; + QPDF_DLL + int getErrno() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat(std::string const& description, int system_errno); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + std::string description; + int system_errno; +}; + +#endif // QPDFSYSTEMERROR_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFTokenizer.hh new file mode 100644 index 0000000..94dae1a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFTokenizer.hh @@ -0,0 +1,218 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFTOKENIZER_HH +#define QPDFTOKENIZER_HH + +#include + +#include + +#include +#include +#include + +namespace qpdf +{ + class Tokenizer; + namespace impl + { + class Parser; + } +} // namespace qpdf + +class QPDFTokenizer +{ + public: + // Token type tt_eof is only returned of allowEOF() is called on the tokenizer. tt_eof was + // introduced in QPDF version 4.1. tt_space, tt_comment, and tt_inline_image were added in QPDF + // version 8. + enum token_type_e { + tt_bad, + tt_array_close, + tt_array_open, + tt_brace_close, + tt_brace_open, + tt_dict_close, + tt_dict_open, + tt_integer, + tt_name, + tt_real, + tt_string, + tt_null, + tt_bool, + tt_word, + tt_eof, + tt_space, + tt_comment, + tt_inline_image, + }; + + class Token + { + public: + Token() : + type(tt_bad) + { + } + QPDF_DLL + Token(token_type_e type, std::string const& value); + Token( + token_type_e type, + std::string const& value, + std::string raw_value, + std::string error_message) : + type(type), + value(value), + raw_value(raw_value), + error_message(error_message) + { + } + token_type_e + getType() const + { + return this->type; + } + std::string const& + getValue() const + { + return this->value; + } + std::string const& + getRawValue() const + { + return this->raw_value; + } + std::string const& + getErrorMessage() const + { + return this->error_message; + } + bool + operator==(Token const& rhs) const + { + // Ignore fields other than type and value + return ( + (this->type != tt_bad) && (this->type == rhs.type) && (this->value == rhs.value)); + } + bool + isInteger() const + { + return this->type == tt_integer; + } + bool + isWord() const + { + return this->type == tt_word; + } + bool + isWord(std::string const& value) const + { + return this->type == tt_word && this->value == value; + } + + private: + token_type_e type; + std::string value; + std::string raw_value; + std::string error_message; + }; + + QPDF_DLL + QPDFTokenizer(); + + QPDF_DLL + ~QPDFTokenizer(); + + // If called, treat EOF as a separate token type instead of an error. This was introduced in + // QPDF 4.1 to facilitate tokenizing content streams. + QPDF_DLL + void allowEOF(); + + // If called, readToken will return "ignorable" tokens for space and comments. This was added in + // QPDF 8. + QPDF_DLL + void includeIgnorable(); + + // There are two modes of operation: push and pull. The pull method is easier but requires an + // input source. The push method is more complicated but can be used to tokenize a stream of + // incoming characters in a pipeline. + + // Push mode: + + // deprecated, please see + + // Keep presenting characters with presentCharacter() and presentEOF() and calling getToken() + // until getToken() returns true. When it does, be sure to check unread_ch and to unread ch if + // it is true. If these are called when a token is available, an exception will be thrown. + QPDF_DLL + void presentCharacter(char ch); + QPDF_DLL + void presentEOF(); + + // If a token is available, return true and initialize token with the token, unread_char with + // whether or not we have to unread the last character, and if unread_char, ch with the + // character to unread. + QPDF_DLL + bool getToken(Token& token, bool& unread_char, char& ch); + + // This function returns true of the current character is between tokens (i.e., white space that + // is not part of a string) or is part of a comment. A tokenizing filter can call this to + // determine whether to output the character. + [[deprecated("see ")]] QPDF_DLL bool + betweenTokens(); + + // Pull mode: + + // Read a token from an input source. Context describes the context in which the token is being + // read and is used in the exception thrown if there is an error. After a token is read, the + // position of the input source returned by input->tell() points to just after the token, and + // the input source's "last offset" as returned by input->getLastOffset() points to the + // beginning of the token. + QPDF_DLL + Token readToken( + InputSource& input, std::string const& context, bool allow_bad = false, size_t max_len = 0); + QPDF_DLL + Token readToken( + std::shared_ptr input, + std::string const& context, + bool allow_bad = false, + size_t max_len = 0); + + // Calling this method puts the tokenizer in a state for reading inline images. You should call + // this method after reading the character following the ID operator. In that state, it will + // return all data up to BUT NOT INCLUDING the next EI token. After you call this method, the + // next call to readToken (or the token created next time getToken returns true) will either be + // tt_inline_image or tt_bad. This is the only way readToken + // returns a tt_inline_image token. + QPDF_DLL + void expectInlineImage(std::shared_ptr input); + QPDF_DLL + void expectInlineImage(InputSource& input); + + private: + friend class qpdf::impl::Parser; + + QPDFTokenizer(QPDFTokenizer const&) = delete; + QPDFTokenizer& operator=(QPDFTokenizer const&) = delete; + + std::unique_ptr m; +}; + +#endif // QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFUsage.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFUsage.hh new file mode 100644 index 0000000..3c5da1b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFUsage.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFUSAGE_HH +#define QPDFUSAGE_HH + +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error +{ + public: + QPDF_DLL + QPDFUsage(std::string const& msg); + ~QPDFUsage() noexcept override = default; +}; + +#endif // QPDFUSAGE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFWriter.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFWriter.hh new file mode 100644 index 0000000..3c3c0b9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFWriter.hh @@ -0,0 +1,455 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFWRITER_HH +#define QPDFWRITER_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace qpdf +{ + class Writer; +} + +class QPDF; + +// This class implements a simple writer for saving QPDF objects to new PDF files. See comments +// through the header file for additional details. +class QPDFWriter +{ + public: + // Construct a QPDFWriter object without specifying output. You must call one of the output + // setting routines defined below. + QPDF_DLL + QPDFWriter(QPDF& pdf); + + // Create a QPDFWriter object that writes its output to a file or to stdout. This is equivalent + // to using the previous constructor and then calling setOutputFilename(). See + // setOutputFilename() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* filename); + + // Create a QPDFWriter object that writes its output to an already open FILE*. This is + // equivalent to calling the first constructor and then calling setOutputFile(). See + // setOutputFile() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* description, FILE* file, bool close_file); + + ~QPDFWriter() = default; + + class QPDF_DLL_CLASS ProgressReporter + { + public: + QPDF_DLL + virtual ~ProgressReporter(); + + // This method is called with a value from 0 to 100 to indicate approximate progress through + // the write process. See registerProgressReporter. + virtual void reportProgress(int) = 0; + }; + + // This is a progress reporter that takes a function. It is used by the C APIs, but it is + // available if you want to just register a C function as a handler. + class QPDF_DLL_CLASS FunctionProgressReporter: public ProgressReporter + { + public: + QPDF_DLL + FunctionProgressReporter(std::function); + QPDF_DLL + ~FunctionProgressReporter() override; + QPDF_DLL + void reportProgress(int) override; + + private: + std::function handler; + }; + + // Setting Output. Output may be set only one time. If you don't use the filename version of + // the QPDFWriter constructor, you must call exactly one of these methods. + + // Passing nullptr as filename means write to stdout. QPDFWriter will create a zero-length + // output file upon construction. If write fails, the empty or partially written file will not + // be deleted. This is by design: sometimes the partial file may be useful for tracking down + // problems. If your application doesn't want the partially written file to be left behind, you + // should delete it if the eventual call to write fails. + QPDF_DLL + void setOutputFilename(char const* filename); + + // Write to the given FILE*, which must be opened by the caller. If close_file is true, + // QPDFWriter will close the file. Otherwise, the caller must close the file. The file does not + // need to be seekable; it will be written to in a single pass. It must be open in binary mode. + QPDF_DLL + void setOutputFile(char const* description, FILE* file, bool close_file); + + // Indicate that QPDFWriter should create a memory buffer to contain the final PDF file. Obtain + // the memory by calling getBuffer(). + QPDF_DLL + void setOutputMemory(); + + // Return the buffer object containing the PDF file. If setOutputMemory() has been called, this + // method may be called exactly one time after write() has returned. The caller is responsible + // for deleting the buffer when done. See also getBufferSharedPointer(). + QPDF_DLL + Buffer* getBuffer(); + + // Return getBuffer() in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // Supply your own pipeline object. Output will be written to this pipeline, and QPDFWriter + // will call finish() on the pipeline. It is the caller's responsibility to manage the memory + // for the pipeline. The pipeline is never deleted by QPDFWriter, which makes it possible for + // you to call additional methods on the pipeline after the writing is finished. + QPDF_DLL + void setOutputPipeline(Pipeline*); + + // Setting Parameters + + // Set the value of object stream mode. In disable mode, we never generate any object streams. + // In preserve mode, we preserve object stream structure from the original file. In generate + // mode, we generate our own object streams. In all cases, we generate a conventional + // cross-reference table if there are no object streams and a cross-reference stream if there + // are object streams. The default is o_preserve. + QPDF_DLL + void setObjectStreamMode(qpdf_object_stream_e); + + // Set value of stream data mode. This is an older interface. Instead of using this, prefer + // setCompressStreams() and setDecodeLevel(). This method is retained for compatibility, but it + // does not cover the full range of available configurations. The mapping between this and the + // new methods is as follows: + // + // qpdf_s_uncompress: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_generalized) + // qpdf_s_preserve: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_none) + // qpdf_s_compress: + // setCompressStreams(true) + // setDecodeLevel(qpdf_dl_generalized) + // + // The default is qpdf_s_compress. + QPDF_DLL + void setStreamDataMode(qpdf_stream_data_e); + + // If true, compress any uncompressed streams when writing them. Metadata streams are a special + // case and are not compressed even if this is true. This is true by default for QPDFWriter. If + // you want QPDFWriter to leave uncompressed streams uncompressed, pass false to this method. + QPDF_DLL + void setCompressStreams(bool); + + // When QPDFWriter encounters streams, this parameter controls the behavior with respect to + // attempting to apply any filters to the streams when copying to the output. The decode levels + // are as follows: + // + // qpdf_dl_none: Do not attempt to apply any filters. Streams remain as they appear in the + // original file. Note that uncompressed streams may still be compressed on output. You can + // disable that by calling setCompressStreams(false). + // + // qpdf_dl_generalized: This is the default. QPDFWriter will apply LZWDecode, ASCII85Decode, + // ASCIIHexDecode, and FlateDecode filters on the input. When combined with + // setCompressStreams(true), which is the default, the effect of this is that streams filtered + // with these older and less efficient filters will be recompressed with the Flate filter. By + // default, as a special case, if a stream is already compressed with FlateDecode and + // setCompressStreams is enabled, the original compressed data will be preserved. This behavior + // can be overridden by calling setRecompressFlate(true). + // + // qpdf_dl_specialized: In addition to uncompressing the generalized compression formats, + // supported non-lossy compression will also be decoded. At present, this includes the + // RunLengthDecode filter. + // + // qpdf_dl_all: In addition to generalized and non-lossy specialized filters, supported lossy + // compression filters will be applied. At present, this includes DCTDecode (JPEG) compression. + // Note that compressing the resulting data with DCTDecode again will accumulate loss, so avoid + // multiple compression and decompression cycles. This is mostly useful for retrieving image + // data. + QPDF_DLL + void setDecodeLevel(qpdf_stream_decode_level_e); + + // By default, when both the input and output contents of a stream are compressed with Flate, + // qpdf does not uncompress and recompress the stream. Passing true here causes it to do so. + // This can be useful if recompressing all streams with a higher compression level, which can be + // set by calling the static method Pl_Flate::setCompressionLevel. + QPDF_DLL + void setRecompressFlate(bool); + + // Set value of content stream normalization. The default is "false". If true, we attempt to + // normalize newlines inside of content streams. Some constructs such as inline images may + // thwart our efforts. There may be some cases where this can damage the content stream. This + // flag should be used only for debugging and experimenting with PDF content streams. Never use + // it for production files. + QPDF_DLL + void setContentNormalization(bool); + + // Set QDF mode. QDF mode causes special "pretty printing" of PDF objects, adds comments for + // easier perusing of files. Resulting PDF files can be edited in a text editor and then run + // through fix-qdf to update cross reference tables and stream lengths. + QPDF_DLL + void setQDFMode(bool); + + // Preserve unreferenced objects. The default behavior is to discard any object that is not + // visited during a traversal of the object structure from the trailer. + QPDF_DLL + void setPreserveUnreferencedObjects(bool); + + // Always write a newline before the endstream keyword. This helps with PDF/A compliance, though + // it is not sufficient for it. + QPDF_DLL + void setNewlineBeforeEndstream(bool); + + // Set the minimum PDF version. If the PDF version of the input file (or previously set minimum + // version) is less than the version passed to this method, the PDF version of the output file + // will be set to this value. If the original PDF file's version or previously set minimum + // version is already this version or later, the original file's version will be used. + // QPDFWriter automatically sets the minimum version to 1.4 when R3 encryption parameters are + // used, and to 1.5 when object streams are used. + QPDF_DLL + void setMinimumPDFVersion(std::string const&, int extension_level = 0); + QPDF_DLL + void setMinimumPDFVersion(PDFVersion const&); + + // Force the PDF version of the output file to be a given version. Use of this function may + // create PDF files that will not work properly with older PDF viewers. When a PDF version is + // set using this function, qpdf will use this version even if the file contains features that + // are not supported in that version of PDF. In other words, you should only use this function + // if you are sure the PDF file in question has no features of newer versions of PDF or if you + // are willing to create files that old viewers may try to open but not be able to properly + // interpret. If any encryption has been applied to the document either explicitly or by + // preserving the encryption of the source document, forcing the PDF version to a value too low + // to support that type of encryption will explicitly disable decryption. Additionally, forcing + // to a version below 1.5 will disable object streams. + QPDF_DLL + void forcePDFVersion(std::string const&, int extension_level = 0); + + // Provide additional text to insert in the PDF file somewhere near the beginning of the file. + // This can be used to add comments to the beginning of a PDF file, for example, if those + // comments are to be consumed by some other application. No checks are performed to ensure + // that the text inserted here is valid PDF. If you want to insert multiline comments, you will + // need to include \n in the string yourself and start each line with %. An extra newline will + // be appended if one is not already present at the end of your text. + QPDF_DLL + void setExtraHeaderText(std::string const&); + + // Causes a deterministic /ID value to be generated. When this is set, the current time and + // output file name are not used as part of /ID generation. Instead, a digest of all significant + // parts of the output file's contents is included in the /ID calculation. Use of a + // deterministic /ID can be handy when it is desirable for a repeat of the same qpdf operation + // on the same inputs being written to the same outputs with the same parameters to generate + // exactly the same results. This feature is incompatible with encrypted files because, for + // encrypted files, the /ID is generated before any part of the file is written since it is an + // input to the encryption process. + QPDF_DLL + void setDeterministicID(bool); + + // Cause a static /ID value to be generated. Use only in test suites. See also + // setDeterministicID. + QPDF_DLL + void setStaticID(bool); + + // Use a fixed initialization vector for AES-CBC encryption. This is not secure. It should be + // used only in test suites for creating predictable encrypted output. + QPDF_DLL + void setStaticAesIV(bool); + + // Suppress inclusion of comments indicating original object IDs when writing QDF files. This + // can also be useful for testing, particularly when using comparison of two qdf files to + // determine whether two PDF files have identical content. + QPDF_DLL + void setSuppressOriginalObjectIDs(bool); + + // Preserve encryption. The default is true unless prefiltering, content normalization, or qdf + // mode has been selected in which case encryption is never preserved. Encryption is also not + // preserved if we explicitly set encryption parameters. + QPDF_DLL + void setPreserveEncryption(bool); + + // Copy encryption parameters from another QPDF object. If you want to copy encryption from the + // object you are writing, call setPreserveEncryption(true) instead. + QPDF_DLL + void copyEncryptionParameters(QPDF&); + + // Set up for encrypted output. User and owner password both must be specified. Either or both + // may be the empty string. Note that qpdf does not apply any special treatment to the empty + // string, which makes it possible to create encrypted files with empty owner passwords and + // non-empty user passwords or with the same password for both user and owner. Some PDF reading + // products don't handle such files very well. Enabling encryption disables stream prefiltering + // and content normalization. Note that setting R2 encryption parameters sets the PDF version + // to at least 1.3, setting R3 encryption parameters pushes the PDF version number to at + // least 1.4, setting R4 parameters pushes the version to at least 1.5, or if AES is used, 1.6, + // and setting R5 or R6 parameters pushes the version to at least 1.7 with extension level 3. + // + // Note about Unicode passwords: the PDF specification requires passwords to be encoded with PDF + // Doc encoding for R <= 4 and UTF-8 for R >= 5. In all cases, these methods take strings of + // bytes as passwords. It is up to the caller to ensure that passwords are properly encoded. The + // qpdf command-line tool tries to do this, as discussed in the manual. If you are doing this + // from your own application, QUtil contains many transcoding functions that could be useful to + // you, most notably utf8_to_pdf_doc. + + // R2 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR2EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_print, + bool allow_modify, + bool allow_extract, + bool allow_annotate); + // R3 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR3EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print); + // When use_aes=false, this call enables R4 with RC4, which is a weak cryptographic algorithm. + // Even with use_aes=true, the overall encryption scheme is weak. Don't use it unless you have + // to. See "Weak Cryptography" in the manual. This encryption format is deprecated in the + // PDF 2.0 specification. + QPDF_DLL + void setR4EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata, + bool use_aes); + // R5 is deprecated. Do not use it for production use. Writing R5 is supported by qpdf + // primarily to generate test files for applications that may need to test R5 support. + QPDF_DLL + void setR5EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata); + // This is the only password-based encryption format supported by the PDF specification. + QPDF_DLL + void setR6EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata_aes); + + // Create linearized output. Disables qdf mode, content normalization, and stream prefiltering. + QPDF_DLL + void setLinearization(bool); + + // For debugging QPDF: provide the name of a file to write pass1 of linearization to. The only + // reason to use this is to debug QPDF. To linearize, QPDF writes out the file in two passes. + // Usually the first pass is discarded, but lots of computations are made in pass 1. If a + // linearized file comes out wrong, it can be helpful to look at the first pass. + QPDF_DLL + void setLinearizationPass1Filename(std::string const&); + + // Create PCLm output. This is only useful for clients that know how to create PCLm files. If a + // file is structured exactly as PCLm requires, this call will tell QPDFWriter to write the PCLm + // header, create certain unreferenced streams required by the standard, and write the objects + // in the required order. Calling this on an ordinary PDF serves no purpose. There is no + // command-line argument that causes this method to be called. + QPDF_DLL + void setPCLm(bool); + + // If you want to be notified of progress, derive a class from ProgressReporter and override the + // reportProgress method. + QPDF_DLL + void registerProgressReporter(std::shared_ptr); + + // Return the PDF version that will be written into the header. Calling this method does all the + // preparation for writing, so it is an error to call any methods that may cause a change to the + // version. Adding new objects to the original file after calling this may also cause problems. + // It is safe to update existing objects or stream contents after calling this method, e.g., to + // include the final version number in metadata. + QPDF_DLL + std::string getFinalVersion(); + + // Write the final file. There is no expectation of being able to call write() more than once. + QPDF_DLL + void write(); + + // Return renumbered ObjGen that was written into the final file. This method can be used after + // calling write(). + QPDF_DLL + QPDFObjGen getRenumberedObjGen(QPDFObjGen); + + // Return XRef entry that was written into the final file. This method can be used after calling + // write(). + QPDF_DLL + std::map getWrittenXRefTable(); + + // The following structs / classes are not part of the public API. + struct Object; + struct NewObject; + class ObjTable; + class NewObjTable; + + private: + friend class qpdf::Writer; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFWRITER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFXRefEntry.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFXRefEntry.hh new file mode 100644 index 0000000..3739131 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QPDFXRefEntry.hh @@ -0,0 +1,73 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFXREFENTRY_HH +#define QPDFXREFENTRY_HH + +#include +#include + +class QPDFXRefEntry +{ + public: + // Type constants are from the PDF spec section "Cross-Reference Streams": + // 0 = free entry; not used + // 1 = "uncompressed"; field 1 = offset + // 2 = "compressed"; field 1 = object stream number, field 2 = index + + // Create a type 0 "free" entry. + QPDF_DLL + QPDFXRefEntry(); + QPDF_DLL + QPDFXRefEntry(int type, qpdf_offset_t field1, int field2); + // Create a type 1 "uncompressed" entry. + QPDFXRefEntry(qpdf_offset_t offset) : + type(1), + field1(offset) + { + } + // Create a type 2 "compressed" entry. + QPDFXRefEntry(int stream_number, int index) : + type(2), + field1(stream_number), + field2(index) + { + } + + QPDF_DLL + int getType() const; + QPDF_DLL + qpdf_offset_t getOffset() const; // only for type 1 + QPDF_DLL + int getObjStreamNumber() const; // only for type 2 + QPDF_DLL + int getObjStreamIndex() const; // only for type 2 + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created. + + // The layout can be changed to reduce the size from 24 to 16 bytes. However, this would have a + // definite runtime cost. + int type{0}; + qpdf_offset_t field1{0}; + int field2{0}; +}; + +#endif // QPDFXREFENTRY_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QTC.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QTC.hh new file mode 100644 index 0000000..a5ecadf --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QTC.hh @@ -0,0 +1,43 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QTC_HH +#define QTC_HH + +#include + +// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC calls in any code that +// includes this file, but QTC will still be built into the library. That way, it is possible to +// build and package qpdf with QPDF_DISABLE_QTC while still making QTC::TC available to end users. + +namespace QTC +{ + QPDF_DLL + void TC_real(char const* const scope, char const* const ccase, int n = 0); + + inline void + TC(char const* const scope, char const* const ccase, int n = 0) + { +#ifndef QPDF_DISABLE_QTC + TC_real(scope, ccase, n); +#endif // QPDF_DISABLE_QTC + } +}; // namespace QTC + +#endif // QTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QUtil.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QUtil.hh new file mode 100644 index 0000000..18d6083 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/QUtil.hh @@ -0,0 +1,512 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QUTIL_HH +#define QUTIL_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RandomDataProvider; +class Pipeline; + +namespace QUtil +{ + // This is a collection of useful utility functions that don't really go anywhere else. + QPDF_DLL + std::string int_to_string(long long, int length = 0); + QPDF_DLL + std::string uint_to_string(unsigned long long, int length = 0); + QPDF_DLL + std::string int_to_string_base(long long, int base, int length = 0); + QPDF_DLL + std::string uint_to_string_base(unsigned long long, int base, int length = 0); + QPDF_DLL + std::string double_to_string(double, int decimal_places = 0, bool trim_trailing_zeroes = true); + + // These string to number methods throw std::runtime_error on underflow/overflow. + QPDF_DLL + long long string_to_ll(char const* str); + QPDF_DLL + int string_to_int(char const* str); + QPDF_DLL + unsigned long long string_to_ull(char const* str); + QPDF_DLL + unsigned int string_to_uint(char const* str); + + // Returns true if this exactly represents a long long. The determination is made by converting + // the string to a long long, then converting the result back to a string, and then comparing + // that result with the original string. + QPDF_DLL + bool is_long_long(char const* str); + + // Pipeline's write method wants unsigned char*, but we often have some other type of string. + // These methods do combinations of const_cast and reinterpret_cast to give us an unsigned + // char*. They should only be used when it is known that it is safe. None of the pipelines in + // qpdf modify the data passed to them, so within qpdf, it should always be safe. + QPDF_DLL + unsigned char* unsigned_char_pointer(std::string const& str); + QPDF_DLL + unsigned char* unsigned_char_pointer(char const* str); + + // Throw QPDFSystemError, which is derived from std::runtime_error, with a string formed by + // appending to "description: " the standard string corresponding to the current value of errno. + // You can retrieve the value of errno by calling getErrno() on the QPDFSystemError. Prior to + // qpdf 8.2.0, this method threw system::runtime_error directly, but since QPDFSystemError is + // derived from system::runtime_error, old code that specifically catches std::runtime_error + // will still work. + QPDF_DLL + void throw_system_error(std::string const& description); + + // The status argument is assumed to be the return value of a standard library call that sets + // errno when it fails. If status is -1, convert the current value of errno to a + // std::runtime_error that includes the standard error string. Otherwise, return status. + QPDF_DLL + int os_wrapper(std::string const& description, int status); + + // If the open fails, throws std::runtime_error. Otherwise, the FILE* is returned. The filename + // should be UTF-8 encoded, even on Windows. It will be converted as needed on Windows. + QPDF_DLL + FILE* safe_fopen(char const* filename, char const* mode); + + // The FILE* argument is assumed to be the return of fopen. If null, throw std::runtime_error. + // Otherwise, return the FILE* argument. + QPDF_DLL + FILE* fopen_wrapper(std::string const&, FILE*); + + // This is a little class to help with automatic closing files. You can do something like + // + // QUtil::FileCloser fc(QUtil::safe_fopen(filename, "rb")); + // + // and then use fc.f to the file. Be sure to actually declare a variable of type FileCloser. + // Using it as a temporary won't work because it will close the file as soon as it goes out of + // scope. + class FileCloser + { + public: + FileCloser(FILE* f) : + f(f) + { + } + + ~FileCloser() + { + if (f) { + fclose(f); + f = nullptr; + } + } + + FILE* f; + }; + + // Attempt to open the file read only and then close again + QPDF_DLL + bool file_can_be_opened(char const* filename); + + // Wrap around off_t versions of fseek and ftell if available + QPDF_DLL + int seek(FILE* stream, qpdf_offset_t offset, int whence); + QPDF_DLL + qpdf_offset_t tell(FILE* stream); + + QPDF_DLL + bool same_file(char const* name1, char const* name2); + + QPDF_DLL + void remove_file(char const* path); + + // rename_file will overwrite newname if it exists + QPDF_DLL + void rename_file(char const* oldname, char const* newname); + + // Write the contents of filename as a binary file to the pipeline. + QPDF_DLL + void pipe_file(char const* filename, Pipeline* p); + + // Return a function that will send the contents of the given file through the given pipeline as + // binary data. + QPDF_DLL + std::function file_provider(std::string const& filename); + + // Return the last path element. On Windows, either / or \ are path separators. Otherwise, only + // / is a path separator. Strip any trailing path separators. Then, if any path separators + // remain, return everything after the last path separator. Otherwise, return the whole string. + // As a special case, if a string consists entirely of path separators, the first character is + // returned. + QPDF_DLL + std::string path_basename(std::string const& filename); + + // Returns a dynamically allocated copy of a string that the caller has to delete with delete[]. + QPDF_DLL + char* copy_string(std::string const&); + + // Returns a shared_ptr with the correct deleter. + QPDF_DLL + std::shared_ptr make_shared_cstr(std::string const&); + + // Copy string as a unique_ptr to an array. + QPDF_DLL + std::unique_ptr make_unique_cstr(std::string const&); + + // Create a shared pointer to an array. From c++20, std::make_shared(n) does this. + template + std::shared_ptr + make_shared_array(size_t n) + { + return std::shared_ptr(new T[n], std::default_delete()); + } + + // Returns lower-case hex-encoded version of the string, treating each character in the input + // string as unsigned. The output string will be twice as long as the input string. + QPDF_DLL + std::string hex_encode(std::string const&); + + // Returns lower-case hex-encoded version of the char including a leading "#". + QPDF_DLL + std::string hex_encode_char(char); + + // Returns a string that is the result of decoding the input string. The input string may + // consist of mixed case hexadecimal digits. Any characters that are not hexadecimal digits will + // be silently ignored. If there are an odd number of hexadecimal digits, a trailing 0 will be + // assumed. + QPDF_DLL + std::string hex_decode(std::string const&); + + // Decode a single hex digit into a char in the range 0 <= char < 16. Return a char >= 16 if + // digit is not a valid hex digit. + QPDF_DLL + char hex_decode_char(char digit); + + // Set stdin, stdout to binary mode + QPDF_DLL + void binary_stdout(); + QPDF_DLL + void binary_stdin(); + // Set stdout to line buffered + QPDF_DLL + void setLineBuf(FILE*); + + // May modify argv0 + QPDF_DLL + char* getWhoami(char* argv0); + + // Get the value of an environment variable in a portable fashion. Returns true iff the variable + // is defined. If `value' is non-null, initializes it with the value of the variable. + QPDF_DLL + bool get_env(std::string const& var, std::string* value = nullptr); + + QPDF_DLL + time_t get_current_time(); + + // Portable structure representing a point in time with second granularity and time zone offset. + struct QPDFTime + { + QPDFTime() = default; + QPDFTime(QPDFTime const&) = default; + QPDFTime& operator=(QPDFTime const&) = default; + QPDFTime(int year, int month, int day, int hour, int minute, int second, int tz_delta) : + year(year), + month(month), + day(day), + hour(hour), + minute(minute), + second(second), + tz_delta(tz_delta) + { + } + int year; // actual year, no 1900 stuff + int month; // 1--12 + int day; // 1--31 + int hour; + int minute; + int second; + int tz_delta; // minutes before UTC + }; + + QPDF_DLL + QPDFTime get_current_qpdf_time(); + + // Convert a QPDFTime structure to a PDF timestamp string, which is "D:yyyymmddhhmmss" where + // is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone offset. may also be + // omitted. + // Examples: "D:20210207161528-05'00'", "D:20210207211528Z", "D:20210207211528". + // See get_current_qpdf_time and the QPDFTime structure above. + QPDF_DLL + std::string qpdf_time_to_pdf_time(QPDFTime const&); + + // Convert QPDFTime to a second-granularity ISO-8601 timestamp. + QPDF_DLL + std::string qpdf_time_to_iso8601(QPDFTime const&); + + // Convert a PDF timestamp string to a QPDFTime. If syntactically valid, return true and fill in + // qtm. If not valid, return false, and do not modify qtm. If qtm is null, just check the + // validity of the string. + QPDF_DLL + bool pdf_time_to_qpdf_time(std::string const&, QPDFTime* qtm = nullptr); + + // Convert PDF timestamp to a second-granularity ISO-8601 timestamp. If syntactically valid, + // return true and initialize iso8601. Otherwise, return false. + bool pdf_time_to_iso8601(std::string const& pdf_time, std::string& iso8601); + + // Return a string containing the byte representation of the UTF-8 encoding for the unicode + // value passed in. + QPDF_DLL + std::string toUTF8(unsigned long uval); + + // Return a string containing the byte representation of the UTF-16 big-endian encoding for the + // unicode value passed in. Unrepresentable code points are converted to U+FFFD. + QPDF_DLL + std::string toUTF16(unsigned long uval); + + // If utf8_val.at(pos) points to the beginning of a valid UTF-8-encoded character, return the + // codepoint of the character and set error to false. Otherwise, return 0xfffd and set error to + // true. In all cases, pos is advanced to the next position that may begin a valid character. + // When the string has been consumed, pos will be set to the string length. It is an error to + // pass a value of pos that is greater than or equal to the length of the string. + QPDF_DLL + unsigned long get_next_utf8_codepoint(std::string const& utf8_val, size_t& pos, bool& error); + + // Test whether this is a UTF-16 string. This is indicated by first two bytes being 0xFE 0xFF + // (big-endian) or 0xFF 0xFE (little-endian), each of which is the encoding of U+FEFF, the + // Unicode marker. Starting in qpdf 10.6.2, this detects little-endian as well as big-endian. + // Even though the PDF spec doesn't allow little-endian, most readers seem to accept it. + QPDF_DLL + bool is_utf16(std::string const&); + + // Test whether this is an explicit UTF-8 string as allowed by the PDF 2.0 spec. This is + // indicated by first three bytes being 0xEF 0xBB 0xBF, which is the UTF-8 encoding of U+FEFF. + QPDF_DLL + bool is_explicit_utf8(std::string const&); + + // Convert a UTF-8 encoded string to UTF-16 big-endian. Unrepresentable code points are + // converted to U+FFFD. + QPDF_DLL + std::string utf8_to_utf16(std::string const& utf8); + + // Convert a UTF-8 encoded string to the specified single-byte encoding system by replacing all + // unsupported characters with the given unknown_char. + QPDF_DLL + std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?'); + + // These versions return true if the conversion was successful and false if any unrepresentable + // characters were found and had to be substituted with the unknown character. + QPDF_DLL + bool utf8_to_ascii(std::string const& utf8, std::string& ascii, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_win_ansi(std::string const& utf8, std::string& win, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_mac_roman(std::string const& utf8, std::string& mac, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_pdf_doc(std::string const& utf8, std::string& pdfdoc, char unknown_char = '?'); + + // Convert a UTF-16 encoded string to UTF-8. Unrepresentable code + // points are converted to U+FFFD. + QPDF_DLL + std::string utf16_to_utf8(std::string const& utf16); + + // Convert from the specified single-byte encoding system to UTF-8. There is no ascii_to_utf8 + // because all ASCII strings are already valid UTF-8. + QPDF_DLL + std::string win_ansi_to_utf8(std::string const& win); + QPDF_DLL + std::string mac_roman_to_utf8(std::string const& mac); + QPDF_DLL + std::string pdf_doc_to_utf8(std::string const& pdfdoc); + + // Analyze a string for encoding. We can't tell the difference between any single-byte + // encodings, and we can't tell for sure whether a string that happens to be valid UTF-8 isn't a + // different encoding, but we can at least tell a few things to help us guess. If there are no + // characters with the high bit set, has_8bit_chars is false, and the other values are also + // false, even though ASCII strings are valid UTF-8. is_valid_utf8 means that the string is + // non-trivially valid UTF-8. Although the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and + // just about everything else) accepts UTF-16LE (as of 10.6.2). + QPDF_DLL + void analyze_encoding( + std::string const& str, bool& has_8bit_chars, bool& is_valid_utf8, bool& is_utf16); + + // Try to compensate for previously incorrectly encoded strings. We want to compensate for the + // following errors: + // + // * The string was supposed to be UTF-8 but was one of the single-byte encodings + // * The string was supposed to be PDF Doc but was either UTF-8 or one of the other single-byte + // encodings + // + // The returned vector always contains the original string first, and then it contains what the + // correct string would be in the event that the original string was the result of any of the + // above errors. + // + // This method is useful for attempting to recover a password that may have been previously + // incorrectly encoded. For example, the password was supposed to be UTF-8 but the previous + // application used a password encoded in WinAnsi, or if the previous password was supposed to + // be PDFDoc but was actually given as UTF-8 or WinAnsi, this method would find the correct + // password. + QPDF_DLL + std::vector possible_repaired_encodings(std::string); + + // Return a cryptographically secure random number. + QPDF_DLL + long random(); + + // Initialize a buffer with cryptographically secure random bytes. + QPDF_DLL + void initializeWithRandomBytes(unsigned char* data, size_t len); + + // Supply a random data provider. Starting in qpdf 10.0.0, qpdf uses the crypto provider as its + // source of random numbers. If you are using the native crypto provider, then qpdf will either + // use the operating system's secure random number source or, only if enabled at build time, an + // insecure random source from stdlib. The caller is responsible for managing the memory for the + // RandomDataProvider. This method modifies a static variable. If you are providing your own + // random data provider, you should call this at the beginning of your program before creating + // any QPDF objects. Passing a null to this method will reset the library back to its default + // random data provider. + QPDF_DLL + void setRandomDataProvider(RandomDataProvider*); + + // This returns the random data provider that would be used the next time qpdf needs random + // data. It will never return null. If no random data provider has been provided and the + // library was not compiled with any random data provider available, an exception will be + // thrown. + QPDF_DLL + RandomDataProvider* getRandomDataProvider(); + + // Filename is UTF-8 encoded, even on Windows, as described in the comments for safe_fopen. + QPDF_DLL + std::list read_lines_from_file(char const* filename, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(std::istream&, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(FILE*, bool preserve_eol = false); + QPDF_DLL + void read_lines_from_file( + std::function next_char, + std::list& lines, + bool preserve_eol = false); + + QPDF_DLL + void read_file_into_memory(char const* filename, std::shared_ptr& file_buf, size_t& size); + + QPDF_DLL + std::string read_file_into_string(char const* filename); + QPDF_DLL + std::string read_file_into_string(FILE* f, std::string_view filename = ""); + + // This used to be called strcasecmp, but that is a macro on some platforms, so we have to give + // it a name that is not likely to be a macro anywhere. + QPDF_DLL + int str_compare_nocase(char const*, char const*); + + // These routines help the tokenizer recognize certain character classes without using ctype, + // which we avoid because of locale considerations. + QPDF_DLL + bool is_hex_digit(char); + + QPDF_DLL + bool is_space(char); + + QPDF_DLL + bool is_digit(char); + + QPDF_DLL + bool is_number(char const*); + + /// @brief Handles the result code from qpdf functions. + /// + /// **For qpdf internal use only - not part of the public API** + /// @par + /// Depending on the result code, either continues execution or throws an + /// exception in case of an invalid parameter. + /// + /// @param result The result code of type qpdf_result_e, indicating success or failure status. + /// @param context A string describing the context where this function is invoked, used for + /// error reporting if an exception is thrown. + /// + /// @throws std::logic_error If the result code is `qpdf_bad_parameter`, indicating an invalid + /// parameter was supplied to a function. The exception message will + /// include the provided context for easier debugging. + /// + /// @since 12.3 + QPDF_DLL + void handle_result_code(qpdf_result_e result, std::string_view context); + + // This method parses the numeric range syntax used by the qpdf command-line tool. May throw + // std::runtime_error. A numeric range is as comma-separated list of groups. A group may be a + // number specification or a range of number specifications separated by a dash. A number + // specification may be one of the following (where is a number): + // * -- the numeric value of n + // * z -- the value of the `max` parameter + // * r -- represents max + 1 - ( from the end) + // + // If the group is two number specifications separated by a dash, it represents the range of + // numbers from the first to the second, inclusive. If the first is greater than the second, the + // numbers are descending. + // + // From qpdf 11.7.1: if a group starts with `x`, its members are excluded from the previous + // group that didn't start with `x1. + // + // Example: with max of 15, the range "4-10,x7-9,12-8,xr5" is 4, 5, 6, 10, 12, 10, 9, 8. This is + // 4 through 10 inclusive without 7 through 9 inclusive followed by 12 to 8 inclusive + // (descending) without 11 (the fifth value counting backwards from 15). For more information + // and additional examples, see the "Page Ranges" section in the manual. + QPDF_DLL + std::vector parse_numrange(char const* range, int max); + +#ifndef QPDF_NO_WCHAR_T + // If you are building qpdf on a stripped down system that doesn't have wchar_t, such as may be + // the case in some embedded environments, you may define QPDF_NO_WCHAR_T in your build. This + // symbol is never defined automatically. Search for wchar_t in qpdf's top-level README.md file + // for details. + + // Take an argv array consisting of wchar_t, as when wmain is invoked, convert all UTF-16 + // encoded strings to UTF-8, and call another main. + QPDF_DLL + int call_main_from_wmain(int argc, wchar_t* argv[], std::function realmain); + QPDF_DLL + int call_main_from_wmain( + int argc, + wchar_t const* const argv[], + std::function realmain); +#endif // QPDF_NO_WCHAR_T + + // Try to return the maximum amount of memory allocated by the current process and its threads. + // Return 0 if unable to determine. This is Linux-specific and not implemented to be completely + // reliable. It is used during development for performance testing to detect changes that may + // significantly change memory usage. It is not recommended for use for other purposes. + QPDF_DLL + size_t get_max_memory_usage(); +}; // namespace QUtil + +#endif // QUTIL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/RandomDataProvider.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/RandomDataProvider.hh new file mode 100644 index 0000000..c929f0f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/RandomDataProvider.hh @@ -0,0 +1,44 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef RANDOMDATAPROVIDER_HH +#define RANDOMDATAPROVIDER_HH + +#include +#include // for size_t + +class QPDF_DLL_CLASS RandomDataProvider +{ + public: + virtual ~RandomDataProvider() = default; + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + protected: + QPDF_DLL_PRIVATE + RandomDataProvider() = default; + + private: + RandomDataProvider(RandomDataProvider const&) = delete; + RandomDataProvider& operator=(RandomDataProvider const&) = delete; +}; + +#endif // RANDOMDATAPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Types.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Types.h new file mode 100644 index 0000000..015cd22 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/Types.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFTYPES_H +#define QPDFTYPES_H + +/* Provide an offset type that should be as big as off_t on just about + * any system. If your compiler doesn't support C99 (or at least the + * "long long" type), then you may have to modify this definition. + */ + +typedef long long int qpdf_offset_t; + +#endif /* QPDFTYPES_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_att.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_att.hh new file mode 100644 index 0000000..ea85419 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_att.hh @@ -0,0 +1,14 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL AttConfig* replace(); +QPDF_DLL AttConfig* key(std::string const& parameter); +QPDF_DLL AttConfig* filename(std::string const& parameter); +QPDF_DLL AttConfig* creationdate(std::string const& parameter); +QPDF_DLL AttConfig* moddate(std::string const& parameter); +QPDF_DLL AttConfig* mimetype(std::string const& parameter); +QPDF_DLL AttConfig* description(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_copy_att.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_copy_att.hh new file mode 100644 index 0000000..764a5ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_copy_att.hh @@ -0,0 +1,9 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL CopyAttConfig* prefix(std::string const& parameter); +QPDF_DLL CopyAttConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_enc.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_enc.hh new file mode 100644 index 0000000..ed4d071 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_enc.hh @@ -0,0 +1,20 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL EncConfig* extract(std::string const& parameter); +QPDF_DLL EncConfig* annotate(std::string const& parameter); +QPDF_DLL EncConfig* print(std::string const& parameter); +QPDF_DLL EncConfig* modify(std::string const& parameter); +QPDF_DLL EncConfig* cleartextMetadata(); +QPDF_DLL EncConfig* forceV4(); +QPDF_DLL EncConfig* accessibility(std::string const& parameter); +QPDF_DLL EncConfig* assemble(std::string const& parameter); +QPDF_DLL EncConfig* form(std::string const& parameter); +QPDF_DLL EncConfig* modifyOther(std::string const& parameter); +QPDF_DLL EncConfig* useAes(std::string const& parameter); +QPDF_DLL EncConfig* forceR5(); +QPDF_DLL EncConfig* allowInsecure(); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_global.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_global.hh new file mode 100644 index 0000000..7f8758b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_global.hh @@ -0,0 +1,13 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL GlobalConfig* noDefaultLimits(); +QPDF_DLL GlobalConfig* parserMaxContainerSize(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxContainerSizeDamaged(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxErrors(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxNesting(std::string const& parameter); +QPDF_DLL GlobalConfig* maxStreamFilters(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_limits.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_limits.hh new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_main.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_main.hh new file mode 100644 index 0000000..0ed4f64 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_main.hh @@ -0,0 +1,97 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL Config* allowWeakCrypto(); +QPDF_DLL Config* check(); +QPDF_DLL Config* checkLinearization(); +QPDF_DLL Config* coalesceContents(); +QPDF_DLL Config* decrypt(); +QPDF_DLL Config* deterministicId(); +QPDF_DLL Config* externalizeInlineImages(); +QPDF_DLL Config* filteredStreamData(); +QPDF_DLL Config* flattenRotation(); +QPDF_DLL Config* generateAppearances(); +QPDF_DLL Config* ignoreXrefStreams(); +QPDF_DLL Config* isEncrypted(); +QPDF_DLL Config* jsonInput(); +QPDF_DLL Config* keepInlineImages(); +QPDF_DLL Config* linearize(); +QPDF_DLL Config* listAttachments(); +QPDF_DLL Config* newlineBeforeEndstream(); +QPDF_DLL Config* noOriginalObjectIds(); +QPDF_DLL Config* noWarn(); +QPDF_DLL Config* optimizeImages(); +QPDF_DLL Config* passwordIsHexKey(); +QPDF_DLL Config* preserveUnreferenced(); +QPDF_DLL Config* preserveUnreferencedResources(); +QPDF_DLL Config* progress(); +QPDF_DLL Config* qdf(); +QPDF_DLL Config* rawStreamData(); +QPDF_DLL Config* recompressFlate(); +QPDF_DLL Config* removeAcroform(); +QPDF_DLL Config* removeInfo(); +QPDF_DLL Config* removeMetadata(); +QPDF_DLL Config* removePageLabels(); +QPDF_DLL Config* removeStructure(); +QPDF_DLL Config* reportMemoryUsage(); +QPDF_DLL Config* requiresPassword(); +QPDF_DLL Config* removeRestrictions(); +QPDF_DLL Config* showEncryption(); +QPDF_DLL Config* showEncryptionKey(); +QPDF_DLL Config* showLinearization(); +QPDF_DLL Config* showNpages(); +QPDF_DLL Config* showPages(); +QPDF_DLL Config* showXref(); +QPDF_DLL Config* staticAesIv(); +QPDF_DLL Config* staticId(); +QPDF_DLL Config* suppressPasswordRecovery(); +QPDF_DLL Config* suppressRecovery(); +QPDF_DLL Config* testJsonSchema(); +QPDF_DLL Config* verbose(); +QPDF_DLL Config* warningExit0(); +QPDF_DLL Config* withImages(); +QPDF_DLL Config* compressionLevel(std::string const& parameter); +QPDF_DLL Config* jpegQuality(std::string const& parameter); +QPDF_DLL Config* copyEncryption(std::string const& parameter); +QPDF_DLL Config* encryptionFilePassword(std::string const& parameter); +QPDF_DLL Config* forceVersion(std::string const& parameter); +QPDF_DLL Config* iiMinBytes(std::string const& parameter); +QPDF_DLL Config* jobJsonFile(std::string const& parameter); +QPDF_DLL Config* jsonObject(std::string const& parameter); +QPDF_DLL Config* keepFilesOpenThreshold(std::string const& parameter); +QPDF_DLL Config* linearizePass1(std::string const& parameter); +QPDF_DLL Config* minVersion(std::string const& parameter); +QPDF_DLL Config* oiMinArea(std::string const& parameter); +QPDF_DLL Config* oiMinHeight(std::string const& parameter); +QPDF_DLL Config* oiMinWidth(std::string const& parameter); +QPDF_DLL Config* password(std::string const& parameter); +QPDF_DLL Config* passwordFile(std::string const& parameter); +QPDF_DLL Config* removeAttachment(std::string const& parameter); +QPDF_DLL Config* rotate(std::string const& parameter); +QPDF_DLL Config* showAttachment(std::string const& parameter); +QPDF_DLL Config* showObject(std::string const& parameter); +QPDF_DLL Config* jsonStreamPrefix(std::string const& parameter); +QPDF_DLL Config* updateFromJson(std::string const& parameter); +QPDF_DLL Config* collate(std::string const& parameter); +QPDF_DLL Config* collate(); +QPDF_DLL Config* splitPages(std::string const& parameter); +QPDF_DLL Config* splitPages(); +QPDF_DLL Config* compressStreams(std::string const& parameter); +QPDF_DLL Config* decodeLevel(std::string const& parameter); +QPDF_DLL Config* flattenAnnotations(std::string const& parameter); +QPDF_DLL Config* jsonKey(std::string const& parameter); +QPDF_DLL Config* jsonStreamData(std::string const& parameter); +QPDF_DLL Config* keepFilesOpen(std::string const& parameter); +QPDF_DLL Config* normalizeContent(std::string const& parameter); +QPDF_DLL Config* objectStreams(std::string const& parameter); +QPDF_DLL Config* passwordMode(std::string const& parameter); +QPDF_DLL Config* removeUnreferencedResources(std::string const& parameter); +QPDF_DLL Config* streamData(std::string const& parameter); +QPDF_DLL Config* json(std::string const& parameter); +QPDF_DLL Config* json(); +QPDF_DLL Config* jsonOutput(std::string const& parameter); +QPDF_DLL Config* jsonOutput(); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_pages.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_pages.hh new file mode 100644 index 0000000..75b0ae5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_pages.hh @@ -0,0 +1,10 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL PagesConfig* file(std::string const& parameter); +QPDF_DLL PagesConfig* range(std::string const& parameter); +QPDF_DLL PagesConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_set_page_labels.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_set_page_labels.hh new file mode 100644 index 0000000..b816d29 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_set_page_labels.hh @@ -0,0 +1,7 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_uo.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_uo.hh new file mode 100644 index 0000000..547ecf3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/auto_job_c_uo.hh @@ -0,0 +1,12 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL UOConfig* file(std::string const& parameter); +QPDF_DLL UOConfig* to(std::string const& parameter); +QPDF_DLL UOConfig* from(std::string const& parameter); +QPDF_DLL UOConfig* repeat(std::string const& parameter); +QPDF_DLL UOConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/global.hh b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/global.hh new file mode 100644 index 0000000..b99ee31 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/global.hh @@ -0,0 +1,264 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef GLOBAL_HH +#define GLOBAL_HH + +#include + +#include +#include + +#include + +namespace qpdf::global +{ + /// Helper function to translate result codes into C++ exceptions - for qpdf internal use only. + inline void + handle_result(qpdf_result_e result) + { + if (result != qpdf_r_ok) { + QUtil::handle_result_code(result, "qpdf::global"); + } + } + + /// Helper function to wrap calls to qpdf_global_get_uint32 - for qpdf internal use only. + inline uint32_t + get_uint32(qpdf_param_e param) + { + uint32_t value; + handle_result(qpdf_global_get_uint32(param, &value)); + return value; + } + + /// Helper function to wrap calls to qpdf_global_set_uint32 - for qpdf internal use only. + inline void + set_uint32(qpdf_param_e param, uint32_t value) + { + handle_result(qpdf_global_set_uint32(param, value)); + } + + /// @brief Retrieves the number of limit errors. + /// + /// Returns the number of times a global limit was exceeded. This item is read only. + /// + /// @return The number of limit errors. + /// + /// @since 12.3 + uint32_t inline limit_errors() + { + return get_uint32(qpdf_p_limit_errors); + } + + namespace options + { + /// @brief Retrieves whether inspection mode is set. + /// + /// @return True if inspection mode is set. + /// + /// @since 12.3 + bool inline inspection_mode() + { + return get_uint32(qpdf_p_inspection_mode) != 0; + } + + /// @brief Set inspection mode if `true` is passed. + /// + /// This function enables restrictive inspection mode if `true` is passed. Inspection mode + /// must be enabled before a QPDF object is created. By default inspection mode is off. + /// Calling `inspection_mode(false)` is not supported and currently is a no-op. + /// + /// @param value A boolean indicating whether to enable (true) inspection mode. + /// + /// @since 12.3 + void inline inspection_mode(bool value) + { + set_uint32(qpdf_p_inspection_mode, value ? QPDF_TRUE : QPDF_FALSE); + } + + /// @brief Retrieves whether default limits are enabled. + /// + /// @return True if default limits are enabled. + /// + /// @since 12.3 + bool inline default_limits() + { + return get_uint32(qpdf_p_default_limits) != 0; + } + + /// @brief Disable all optional default limits if `false` is passed. + /// + /// This function disables all optional default limits if `false` is passed. Once default + /// values have been disabled they cannot be re-enabled. Passing `true` has no effect. This + /// function will leave any limits that have been explicitly set unchanged. Some limits, + /// such as limits imposed to avoid stack overflows, cannot be disabled but can be changed. + /// + /// @param value A boolean indicating whether to disable (false) the default limits. + /// + /// @since 12.3 + void inline default_limits(bool value) + { + set_uint32(qpdf_p_default_limits, value ? QPDF_TRUE : QPDF_FALSE); + } + + } // namespace options + + namespace limits + { + /// @brief Retrieves the maximum nesting level while parsing objects. + /// + /// @return The maximum nesting level while parsing objects. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + uint32_t inline parser_max_nesting() + { + return get_uint32(qpdf_p_parser_max_nesting); + } + + /// @brief Sets the maximum nesting level while parsing objects. + /// + /// @param value The maximum nesting level to set. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + void inline parser_max_nesting(uint32_t value) + { + set_uint32(qpdf_p_parser_max_nesting, value); + } + + /// @brief Retrieves the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @return The maximum number of errors allowed while parsing objects. + /// + /// @since 12.3 + uint32_t inline parser_max_errors() + { + return get_uint32(qpdf_p_parser_max_errors); + } + + /// Sets the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @param value The maximum number of errors allowed while parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_errors(uint32_t value) + { + set_uint32(qpdf_p_parser_max_errors, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size() + { + return get_uint32(qpdf_p_parser_max_container_size); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing objects. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing xref streams. The default limit is 5,000. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size_damaged() + { + return get_uint32(qpdf_p_parser_max_container_size_damaged); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing trailer dictionaries and xref streams. The + /// default limit is 5,000. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size_damaged(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size_damaged, value); + } + + /// @brief Retrieves the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @return The maximum number of filters allowed when filtering streams. + /// + /// @since 12.3 + uint32_t inline max_stream_filters() + { + return get_uint32(qpdf_p_max_stream_filters); + } + + /// @brief Sets the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @param value The maximum number of filters allowed when filtering streams to set. + /// + /// @since 12.3 + void inline max_stream_filters(uint32_t value) + { + set_uint32(qpdf_p_max_stream_filters, value); + } + } // namespace limits + +} // namespace qpdf::global + +#endif // GLOBAL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdf-c.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdf-c.h new file mode 100644 index 0000000..c602f9f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdf-c.h @@ -0,0 +1,1070 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDF_C_H +#define QPDF_C_H + +/* + * This file defines a basic "C" API for qpdf. It provides access to a subset of the QPDF library's + * capabilities to make them accessible to callers who can't handle calling C++ functions or working + * with C++ classes. This may be especially useful to Windows users who are accessing the qpdf DLL + * directly or to other people programming in non-C/C++ languages that can call C code but not C++ + * code. Starting with qpdf 11.7, it is possible to write your own `extern "C"` functions that + * interoperate with the C API. + * + * There are several things to keep in mind when using the C API. + * + * Error handling is tricky because the underlying C++ API uses exception handling. See "ERROR + * HANDLING" below for a detailed explanation. + * + * The C API is not as rich as the C++ API. For many operations, you must use the C++ API. The C + * API is primarily useful for doing basic transformations on PDF files similar to what you + * might do with the qpdf command-line tool. You can write your own `extern "C"` functions in + * C++ that interoperate with the C API by using qpdf_c_get_qpdf and qpdf_c_wrap which were + * introduced in qpdf 11.7.0. + * + * These functions store their state in a qpdf_data object. Individual instances of qpdf_data + * are not thread-safe: although you may access different qpdf_data objects from different + * threads, you may not access one qpdf_data simultaneously from multiple threads. + * + * All dynamic memory, except for that of the qpdf_data object itself, is managed by the library + * unless otherwise noted. You must create a qpdf_data object using qpdf_init and free it using + * qpdf_cleanup. + * + * Many functions return char*. In all cases, the char* values returned are pointers to data + * inside the qpdf_data object. As such, they are always freed by qpdf_cleanup. In most cases, + * strings returned by functions here may be invalidated by subsequent function calls, sometimes + * even to different functions. If you want a string to last past the next qpdf call or after a + * call to qpdf_cleanup, you should make a copy of it. + * + * Since it is possible for a PDF string to contain null characters, a function that returns + * data originating from a PDF string may also contain null characters. To handle that case, you + * call qpdf_get_last_string_length() to get the length of whatever string was just returned. + * See STRING FUNCTIONS below. + * + * Most functions defined here have obvious counterparts that are methods to either QPDF or + * QPDFWriter. Please see comments in QPDF.hh and QPDFWriter.hh for details on their use. In + * order to avoid duplication of information, comments here focus primarily on differences + * between the C and C++ API. + */ + +/* ERROR HANDLING -- changed in qpdf 10.5 */ + +/* SUMMARY: The only way to know whether a function that does not return an error code has + * encountered an error is to call qpdf_has_error after each function. You can do this even for + * functions that do return error codes. You can also call qpdf_silence_errors to prevent qpdf from + * writing these errors to stderr. + * + * DETAILS: + * + * The data type underlying qpdf_data maintains a list of warnings and a single error. To retrieve + * warnings, call qpdf_next_warning while qpdf_more_warnings is true. To retrieve the error, call + * qpdf_get_error when qpdf_has_error is true. + * + * There are several things that are important to understand. + * + * Some functions return an error code. The value of the error code is made up of a bitwise-OR of + * QPDF_WARNINGS and QPDF_ERRORS. The QPDF_ERRORS bit is set if there was an error during the *most + * recent call* to the API. The QPDF_WARNINGS bit is set if there are any warnings that have not yet + * been retrieved by calling qpdf_more_warnings. It is possible for both its or neither bit to be + * set. + * + * The expected mode of operation is to go through a series of operations, checking for errors after + * each call, but only checking for warnings at the end. This is similar to how it works in the C++ + * API where warnings are handled in exactly this way but errors result in exceptions being thrown. + * However, in both the C and C++ API, it is possible to check for and handle warnings as they + * arise. + * + * Some functions return values (or void) rather than an error code. This is especially true with + * the object handling functions. Those functions can still generate errors. To handle errors in + * those cases, you should explicitly call qpdf_has_error(). Note that, if you want to avoid the + * inconsistencies in the interface, you can always check for error conditions in this way rather + * than looking at status return codes. + * + * Prior to qpdf 10.5, if one of the functions that does not return an error code encountered an + * exception, it would cause the entire program to crash. Starting in qpdf 10.5, the default + * response to an error condition in these situations is to print the error to standard error, issue + * exactly one warning indicating that such an error occurred, and return a sensible fallback value + * (0 for numbers, QPDF_FALSE for booleans, "" for strings, or a null or uninitialized object + * handle). This is better than the old behavior but still undesirable as the best option is to + * explicitly check for error conditions. + * + * To prevent qpdf from writing error messages to stderr in this way, you can call + * qpdf_silence_errors(). This signals to the qpdf library that you intend to check the error codes + * yourself. + * + * If you encounter a situation where an exception from the C++ code is not properly converted to an + * error as described above, it is a bug in qpdf, which should be reported at + * https://github.com/qpdf/qpdf/issues/new. + */ + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _qpdf_data* qpdf_data; + typedef struct _qpdf_error* qpdf_error; + + /* Many functions return an integer error code. Codes are defined below. See comments at the + * top of the file for details. Note that the values below can be logically orred together. + */ + typedef int QPDF_ERROR_CODE; +#define QPDF_SUCCESS 0 +#define QPDF_WARNINGS 1 << 0 +#define QPDF_ERRORS 1 << 1 + + typedef int QPDF_BOOL; +#define QPDF_TRUE 1 +#define QPDF_FALSE 0 + + /* From qpdf 10.5: call this method to signal to the library that you are explicitly handling + * errors from functions that don't return error codes. Otherwise, the library will print these + * error conditions to stderr and issue a warning. Prior to 10.5, the program would have + * crashed from an unhandled exception. + */ + QPDF_DLL + void qpdf_silence_errors(qpdf_data qpdf); + + /* Returns the version of the qpdf software. This is guaranteed to be a static value. + */ + QPDF_DLL + char const* qpdf_get_qpdf_version(); + + /* Returns dynamically allocated qpdf_data pointer; must be freed by calling qpdf_cleanup. You + * must call qpdf_read, one of the other qpdf_read_* functions, or qpdf_empty_pdf before calling + * any function that would need to operate on the PDF file. + */ + QPDF_DLL + qpdf_data qpdf_init(); + + /* Pass a pointer to the qpdf_data pointer created by qpdf_init to clean up resources. This does + * not include buffers initialized by functions that return stream data but it otherwise + * includes all data associated with the QPDF object or any object handles. + */ + QPDF_DLL + void qpdf_cleanup(qpdf_data* qpdf); + + /* ERROR REPORTING */ + + /* Returns 1 if there is an error condition. The error condition can be retrieved by a single + * call to qpdf_get_error. + */ + QPDF_DLL + QPDF_BOOL qpdf_has_error(qpdf_data qpdf); + + /* Returns the error condition, if any. The return value is a pointer to data that will become + * invalid after the next call to this function, qpdf_next_warning, or qpdf_cleanup. After this + * function is called, qpdf_has_error will return QPDF_FALSE until the next error condition + * occurs. If there is no error condition, this function returns a null pointer. + */ + QPDF_DLL + qpdf_error qpdf_get_error(qpdf_data qpdf); + + /* Returns 1 if there are any unretrieved warnings, and zero otherwise. + */ + QPDF_DLL + QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf); + + /* If there are any warnings, returns a pointer to the next warning. Otherwise returns a null + * pointer. + */ + QPDF_DLL + qpdf_error qpdf_next_warning(qpdf_data qpdf); + + /* Extract fields of the error. */ + + /* Use this function to get a full error message suitable for showing to the user. */ + QPDF_DLL + char const* qpdf_get_error_full_text(qpdf_data q, qpdf_error e); + + /* Use these functions to extract individual fields from the error; see QPDFExc.hh for details. + */ + QPDF_DLL + enum qpdf_error_code_e qpdf_get_error_code(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_filename(qpdf_data q, qpdf_error e); + QPDF_DLL + unsigned long long qpdf_get_error_file_position(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_message_detail(qpdf_data q, qpdf_error e); + + /* By default, warnings are written to stderr. Passing true to this function will prevent + * warnings from being written to stderr. They will still be available by calls to + * qpdf_next_warning. + */ + QPDF_DLL + void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value); + + /* LOG FUNCTIONS */ + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdf_set_logger(qpdf_data qpdf, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdf_get_logger(qpdf_data qpdf); + + /* CHECK FUNCTIONS */ + + /* Attempt to read the entire PDF file to see if there are any errors qpdf can detect. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf); + + /* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */ + + QPDF_DLL + void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value); + + /* PROCESS FUNCTIONS */ + + /* This functions process a PDF or JSON input source. */ + + /* Calling qpdf_read causes processFile to be called in the C++ API. Basic parsing is + * performed, but data from the file is only read as needed. For files without passwords, pass + * a null pointer or an empty string as the password. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_read(qpdf_data qpdf, char const* filename, char const* password); + + /* Calling qpdf_read_memory causes processMemoryFile to be called in the C++ API. Otherwise, it + * behaves in the same way as qpdf_read. The description argument will be used in place of the + * file name in any error or warning messages generated by the library. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_read_memory( + qpdf_data qpdf, + char const* description, + char const* buffer, + unsigned long long size, + char const* password); + + /* Calling qpdf_empty_pdf initializes this qpdf object with an empty PDF, making it possible to + * create a PDF from scratch using the C API. Added in 10.6. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf); + + /* Create a PDF from a JSON file. This calls createFromJSON in the C++ API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_file(qpdf_data qpdf, char const* filename); + + /* Create a PDF from JSON data in a null-terminated string. This calls createFromJSON in the C++ + * API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* JSON UPDATE FUNCTIONS */ + + /* Update a QPDF object from a JSON file or buffer. These functions call updateFromJSON. One of + * the other processing functions has to be called first so that the QPDF object is initialized + * with PDF data. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_file(qpdf_data qpdf, char const* filename); + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* READ FUNCTIONS */ + + /* Read functions below must be called after qpdf_read or any of the other functions that + * process a PDF. */ + + /* + * NOTE: Functions that return char* are returning a pointer to an internal buffer that will be + * reused for each call to a function that returns a char*. You must use or copy the value + * before calling any other qpdf library functions. + */ + + /* Return the version of the PDF file. See warning above about functions that return char*. */ + QPDF_DLL + char const* qpdf_get_pdf_version(qpdf_data qpdf); + + /* Return the extension level of the PDF file. */ + QPDF_DLL + int qpdf_get_pdf_extension_level(qpdf_data qpdf); + + /* Return the user password. If the file is opened using the owner password, the user password + * may be retrieved using this function. If the file is opened using the user password, this + * function will return that user password. See warning above about functions that return + * char*. + */ + QPDF_DLL + char const* qpdf_get_user_password(qpdf_data qpdf); + + /* Return the string value of a key in the document's Info dictionary. The key parameter should + * include the leading slash, e.g. "/Author". If the key is not present or has a non-string + * value, a null pointer is returned. Otherwise, a pointer to an internal buffer is returned. + * See warning above about functions that return char*. + */ + QPDF_DLL + char const* qpdf_get_info_key(qpdf_data qpdf, char const* key); + + /* Set a value in the info dictionary, possibly replacing an existing value. The key must + * include the leading slash (e.g. "/Author"). Passing a null pointer as a value will remove + * the key from the info dictionary. Otherwise, a copy will be made of the string that is + * passed in. + */ + QPDF_DLL + void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value); + + /* Indicate whether the input file is linearized. */ + QPDF_DLL + QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf); + + /* Indicate whether the input file is encrypted. */ + QPDF_DLL + QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf); + + QPDF_DLL + QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf); + + /* JSON WRITE FUNCTIONS */ + + /* This function serializes the PDF to JSON. This calls writeJSON from the C++ API. + * + * - version: the JSON version, currently must be 2 + * - fn: a function that will be called with blocks of JSON data; will be called with data, a + * length, and the value of the udata parameter to this function + * - udata: will be passed as the third argument to fn with each call; use this for your own + * tracking or pass a null pointer if you don't need it + * - For decode_level, json_stream_data, file_prefix, and wanted_objects, see comments in + * QPDF.hh. For this API, wanted_objects should be a null-terminated array of null-terminated + * strings. Pass a null pointer if you want all objects. + */ + + /* Function should return 0 on success. */ + typedef int (*qpdf_write_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + QPDF_ERROR_CODE qpdf_write_json( + qpdf_data qpdf, + int version, + qpdf_write_fn_t fn, + void* udata, + enum qpdf_stream_decode_level_e decode_level, + enum qpdf_json_stream_data_e json_stream_data, + char const* file_prefix, + char const* const* wanted_objects); + + /* WRITE FUNCTIONS */ + + /* Set up for writing. No writing is actually performed until the call to qpdf_write(). + */ + + /* Supply the name of the file to be written and initialize the qpdf_data object to handle + * writing operations. This function also attempts to create the file. The PDF data is not + * written until the call to qpdf_write. qpdf_init_write may be called multiple times for the + * same qpdf_data object. When qpdf_init_write is called, all information from previous calls + * to functions that set write parameters (qpdf_set_linearization, etc.) is lost, so any write + * parameter functions must be called again. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename); + + /* Initialize for writing but indicate that the PDF file should be written to memory. Call + * qpdf_get_buffer_length and qpdf_get_buffer to retrieve the resulting buffer. The memory + * containing the PDF file will be destroyed when qpdf_cleanup is called. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf); + + /* Retrieve the buffer used if the file was written to memory. qpdf_get_buffer returns a null + * pointer if data was not written to memory. The memory is freed when qpdf_cleanup is called + * or if a subsequent call to qpdf_init_write or qpdf_init_write_memory is called. */ + QPDF_DLL + size_t qpdf_get_buffer_length(qpdf_data qpdf); + QPDF_DLL + unsigned char const* qpdf_get_buffer(qpdf_data qpdf); + + QPDF_DLL + void qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode); + + QPDF_DLL + void qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode); + + QPDF_DLL + void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_decode_level(qpdf_data qpdf, enum qpdf_stream_decode_level_e level); + + QPDF_DLL + void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_ID except in test suites to suppress generation of a random /ID. + * See also qpdf_set_deterministic_ID. + */ + QPDF_DLL + void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_aes_IV except in test suites to create predictable AES encrypted + * output. + */ + QPDF_DLL + void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_suppress_original_object_IDs(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value); + + /* The *_insecure functions are identical to the old versions but have been renamed as a an + * alert to the caller that they are insecure. See "Weak Cryptographic" in the manual for + * details. + */ + QPDF_DLL + void qpdf_set_r2_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_print, + QPDF_BOOL allow_modify, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_annotate); + + QPDF_DLL + void qpdf_set_r3_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print); + + QPDF_DLL + void qpdf_set_r4_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata, + QPDF_BOOL use_aes); + + QPDF_DLL + void qpdf_set_r5_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_r6_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void qpdf_set_minimum_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level); + + QPDF_DLL + void qpdf_force_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void + qpdf_force_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level); + + /* During write, your report_progress function will be called with a value between 0 and 100 + * representing the approximate write progress. The data object you pass to + * qpdf_register_progress_reporter will be handed back to your function. This function must be + * called after qpdf_init_write (or qpdf_init_write_memory) and before qpdf_write. The + * registered progress reporter applies only to a single write, so you must call it again if you + * perform a subsequent write with a new writer. + */ + QPDF_DLL + void qpdf_register_progress_reporter( + qpdf_data qpdf, void (*report_progress)(int percent, void* data), void* data); + + /* Do actual write operation. */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf); + + /* Object handling. + * + * These functions take and return a qpdf_oh object handle, which is just an unsigned integer. + * The value 0 is never returned, which makes it usable as an uninitialized value. The handles + * returned by these functions are guaranteed to be unique, i.e. two calls to (the same of + * different) functions will return distinct handles even when they refer to the same object. + * + * Each function below, starting with qpdf_oh, corresponds to a specific method of + * QPDFObjectHandler. For example, qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If + * the C++ method is overloaded, the C function's name will be disambiguated. If the C++ method + * takes optional arguments, the C function will have required arguments in those positions. For + * details about the method, please see comments in QPDFObjectHandle.hh. Comments here only + * explain things that are specific to the "C" API. + * + * Only a fraction of the methods of QPDFObjectHandle are available here. Most of the basic + * methods for creating, accessing, and modifying most types of objects are present. Most of the + * higher-level functions are not implemented. Functions for dealing with content streams as + * well as objects that only exist in content streams (operators and inline images) are mostly + * not provided. + * + * To refer to a specific QPDFObjectHandle, you need a pair consisting of a qpdf_data and a + * qpdf_oh, which is just an index into an internal table of objects. All memory allocated by + * any of these functions is returned when qpdf_cleanup is called. + * + * Regarding memory, the same rules apply as the above functions. Specifically, if a function + * returns a char*, the memory is managed by the library and, unless otherwise specified, is not + * expected to be valid after the next qpdf call. + * + * The qpdf_data object keeps a cache of handles returned by these functions. Once you are + * finished referencing a handle, you can optionally release it. Releasing handles is optional + * since they will all get released by qpdf_cleanup, but it can help to reduce the memory + * footprint of the qpdf_data object to release them when you're done. Releasing a handle does + * not destroy the object. All QPDFObjectHandle objects are deleted when they are no longer + * referenced. Releasing an object handle simply invalidates it. For example, if you create an + * object, add it to an existing dictionary or array, and then release its handle, the object is + * safely part of the dictionary or array. Similarly, any other object handle referring to the + * object remains valid. Explicitly releasing an object handle is essentially the same as + * letting a QPDFObjectHandle go out of scope in the C++ API. + * + * Please see "ERROR HANDLING" above for details on how error conditions are handled. + */ + + /* For examples of using this API, see examples/pdf-c-objects.c */ + + typedef unsigned int qpdf_oh; + + /* Releasing objects -- see comments above. These functions have no equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_oh_release_all(qpdf_data qpdf); + + /* Clone an object handle */ + QPDF_DLL + qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh); + + /* Get trailer and root objects */ + QPDF_DLL + qpdf_oh qpdf_get_trailer(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_get_root(qpdf_data qpdf); + + /* Retrieve and replace indirect objects */ + QPDF_DLL + qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh); + + /* Wrappers around QPDFObjectHandle methods. Be sure to read corresponding comments in + * QPDFObjectHandle.hh to understand what each function does and what kinds of objects it + * applies to. Note that names are to appear in a canonicalized form starting with a leading + * slash and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle.hh + * for details. + */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary_of_type( + qpdf_data qpdf, qpdf_oh oh, char const* type, char const* subtype); + + QPDF_DLL + enum qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str); + + QPDF_DLL + QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value); + + QPDF_DLL + long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value); + QPDF_DLL + int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value); + QPDF_DLL + unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value); + QPDF_DLL + unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value); + + QPDF_DLL + char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value); + + QPDF_DLL + char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + /* Return the length of the last string returned. This enables you to retrieve the entire string + * for cases in which a char* returned by one of the functions below points to a string with + * embedded null characters. The function qpdf_oh_get_binary_string_value takes a length + * pointer, which can be useful if you are retrieving the value of a string that is expected to + * contain binary data, such as a checksum or document ID. It is always valid to call + * qpdf_get_last_string_length, but it is usually not necessary as C strings returned by the + * library are only expected to be able to contain null characters if their values originate + * from PDF strings in the input. + */ + QPDF_DLL + size_t qpdf_get_last_string_length(qpdf_data qpdf); + + QPDF_DLL + char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + + QPDF_DLL + int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n); + + /* In all dictionary APIs, keys are specified/represented as canonicalized name strings starting + * with / and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle for + * details. + */ + + /* "C"-specific dictionary key iteration */ + + /* Iteration is allowed on only one dictionary at a time. */ + QPDF_DLL + void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh dict); + QPDF_DLL + QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf); + /* The memory returned by qpdf_oh_dict_next_key is owned by qpdf_data. It is good until the next + * call to qpdf_oh_dict_next_key with the same qpdf_data object. Calling the function again, + * even with a different dict, invalidates previous return values. + */ + QPDF_DLL + char const* qpdf_oh_dict_next_key(qpdf_data qpdf); + + /* end "C"-specific dictionary key iteration */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_null(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value); + QPDF_DLL + qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf, double value, int decimal_places); + QPDF_DLL + qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name); + QPDF_DLL + qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str); + QPDF_DLL + qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str); + /* Use qpdf_oh_new_binary_string for creating a string that may contain arbitrary binary data + * including embedded null characters. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_array(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf); + + /* Create a new stream. Use qpdf_oh_get_dict to get (and subsequently modify) the stream + * dictionary if needed. See comments in QPDFObjectHandle.hh for newStream() for additional + * notes. You must call qpdf_oh_replace_stream_data to provide data for the stream. See STREAM + * FUNCTIONS below. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf); + + QPDF_DLL + void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item); + QPDF_DLL + void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at); + + QPDF_DLL + void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + QPDF_DLL + void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + + QPDF_DLL + qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh); + + /* Note about foreign objects: the C API does not have enough information in the value of a + * qpdf_oh to know what QPDF object it belongs to. To uniquely specify a qpdf object handle from + * a specific qpdf_data instance, you always pair the qpdf_oh with the correct qpdf_data. + * Otherwise, you are likely to get completely the wrong object if you are not lucky enough to + * get an error about the object being invalid. + */ + + /* Copy foreign object: the qpdf_oh returned belongs to `qpdf`, while `foreign_oh` belongs to + * `other_qpdf`. + */ + QPDF_DLL + qpdf_oh qpdf_oh_copy_foreign_object(qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh); + + /* STREAM FUNCTIONS */ + + /* These functions provide basic access to streams and stream data. They are not as + * comprehensive as what is in QPDFObjectHandle, but they do allow for working with streams and + * stream data as caller-managed memory. + */ + + /* Get stream data as a buffer. The buffer is allocated with malloc and must be freed by the + * caller. The size of the buffer is stored in *len. The arguments are similar to those in + * QPDFObjectHandle::pipeStreamData. To get raw stream data, pass qpdf_dl_none as decode_level. + * Otherwise, filtering is attempted and *filtered is set to indicate whether it was successful. + * If *filtered is QPDF_FALSE, then raw, unfiltered stream data was returned. You may pass a + * null pointer as filtered if you don't care about the result. If you pass a null pointer as + * bufp (and len), the value of filtered will be set to whether the stream can be filterable. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + enum qpdf_stream_decode_level_e decode_level, + QPDF_BOOL* filtered, + unsigned char** bufp, + size_t* len); + + /* This function returns the concatenation of all of a page's content streams as a single, + * dynamically allocated buffer. As with qpdf_oh_get_stream_data, the buffer is allocated with + * malloc and must be freed by the caller. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_page_content_data( + qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len); + + /* Call free to release a buffer allocated with malloc. This function can be used to free + * buffers that were dynamically allocated by qpdf functions such as qpdf_oh_get_stream_data or + * qpdf_oh_get_page_content_data. The caller is responsible for calling qpdf_oh_free_buffer (or + * calling free directly) to manage memory properly and avoid memory leaks. This function has no + * equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_free_buffer(unsigned char** bufp); + + /* The data pointed to by bufp will be copied by the library. It does not need to remain valid + * after the call returns. + */ + QPDF_DLL + void qpdf_oh_replace_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + unsigned char const* buf, + size_t len, + qpdf_oh filter, + qpdf_oh decode_parms); + + /* PAGE FUNCTIONS */ + + /* The first time a page function is called, qpdf will traverse the /Pages tree. Subsequent + * calls to retrieve the number of pages or a specific page run in constant time as they are + * accessing the pages cache. If you manipulate the page tree outside of these functions, you + * should call qpdf_update_all_pages_cache. See comments for getAllPages() and + * updateAllPagesCache() in QPDF.hh. + */ + + /* For each function, the corresponding method in QPDF.hh is referenced. Please see comments in + * QPDF.hh for details. + */ + + /* calls getAllPages(). On error, returns -1 and sets error for qpdf_get_error. */ + QPDF_DLL + int qpdf_get_num_pages(qpdf_data qpdf); + /* returns uninitialized object if out of range */ + QPDF_DLL + qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index); + + /* updateAllPagesCache() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf); + + /* findPage() -- return zero-based index. If page is not found, return -1 and save the error to + * be retrieved with qpdf_get_error. + */ + QPDF_DLL + int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh); + + /* pushInheritedAttributesToPage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf); + + /* Functions that add pages may add pages from other files. If adding a page from the same file, + newpage_qpdf and qpdf are the same. + */ + + /* addPage() */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_add_page(qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first); + /* addPageAt() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_add_page_at( + qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL before, qpdf_oh refpage); + /* removePage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page); + + /* GLOBAL OPTIONS AND SETTINGS */ + + QPDF_DLL + /** + * @brief Retrieves a 32-bit unsigned integer value associated with a global option or limit. + * + * This function allows querying of specific parameters, identified by the qpdf_param_e enum, + * and retrieves their associated unsigned 32-bit integer values. The result will be stored in + * the variable pointed to by `value`. For details about the available parameters and their + * meanings see `qpdf/global.hh`. + * + * @param param[in] The parameter for which the value is being retrieved. This must be a valid + * value from the qpdf_param_e enumeration. + * @param value[out] A pointer to a uint32_t to store the retrieved value. This must be a valid, + * non-null pointer. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_get_uint32(enum qpdf_param_e param, uint32_t* value); + + QPDF_DLL + /** + * @brief Sets a global option or limit for the qpdf library to a specified value. + * + * This function is used to configure global options or limits for the qpdf library based on the + * provided parameter and value. The behavior depends on the specific `param` provided and its + * valid range of values. For details about the available parameters and their meanings see + * `qpdf/global.hh`. + * + * @param param[in] The parameter to be set. Must be one of the values defined in the + * qpdf_param_e enumeration. + * @param value[in] The value to assign to the specified parameter. Interpretation of this value + * depends on the parameter being set. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_set_uint32(enum qpdf_param_e param, uint32_t value); +#ifdef __cplusplus +} + +// These C++ functions make it easier to write C++ code that interoperates with the C API. +// See examples/extend-c-api. + +# include +# include + +# include + +// Retrieve the real QPDF object attached to this qpdf_data. +QPDF_DLL +std::shared_ptr qpdf_c_get_qpdf(qpdf_data qpdf); + +// Wrap a C++ function that may throw an exception to translate the exception for retrieval using +// the normal QPDF C API methods. +QPDF_DLL +QPDF_ERROR_CODE qpdf_c_wrap(qpdf_data qpdf, std::function fn); +#endif + +#endif /* QPDF_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdfjob-c.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdfjob-c.h new file mode 100644 index 0000000..a00b923 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdfjob-c.h @@ -0,0 +1,156 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFJOB_C_H +#define QPDFJOB_C_H + +/* + * This file defines a basic "C" API for QPDFJob. See also qpdf-c.h, which defines an API that + * exposes more of the library's API. This API is primarily intended to make it simpler for programs + * in languages other than C++ to incorporate functionality that could be run directly from the + * command-line. + */ + +#include +#include +#include +#include +#ifndef QPDF_NO_WCHAR_T +# include +#endif + +/* + * This file provides a minimal wrapper around QPDFJob. See examples/qpdfjob-c.c for an example of + * its use. + */ + +#ifdef __cplusplus +extern "C" { +#endif + /* SHORT INTERFACE -- These functions are single calls that take care of the whole life cycle of + * QPDFJob. They can be used for one-shot operations where no additional configuration is + * needed. See FULL INTERFACE below. */ + + /* This function does the equivalent of running the qpdf command-line with the given arguments + * and returns the exit code that qpdf would use. argv must be a null-terminated array of + * null-terminated UTF8-encoded strings. If calling this from wmain on Windows, use + * qpdfjob_run_from_wide_argv instead. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_argv(char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_run_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_run_from_wide_argv(wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function runs QPDFJob from a job JSON file. See the "QPDF Job" section of the manual for + * details. The JSON string must be UTF8-encoded. It returns the error code that qpdf would + * return with the equivalent command-line invocation. Exit code values are defined in + * Constants.h in the qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_json(char const* json); + + /* FULL INTERFACE -- new in qpdf11. Similar to the qpdf-c.h API, you must call qpdfjob_init to + * get a qpdfjob_handle and, when done, call qpdfjob_cleanup to free resources. Remaining + * methods take qpdfjob_handle as an argument. This interface requires more calls but also + * offers greater flexibility. + */ + typedef struct _qpdfjob_handle* qpdfjob_handle; + QPDF_DLL + qpdfjob_handle qpdfjob_init(); + + QPDF_DLL + void qpdfjob_cleanup(qpdfjob_handle* j); + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdfjob_set_logger(qpdfjob_handle j, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdfjob_get_logger(qpdfjob_handle j); + + /* This function wraps QPDFJob::initializeFromArgv. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_initialize_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_initialize_from_wide_argv(qpdfjob_handle j, wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function wraps QPDFJob::initializeFromJson. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions using this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json); + + /* This function wraps QPDFJob::run. It returns the error code that qpdf would return with the + * equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run(qpdfjob_handle j); + + /* The following two functions allow a job to be run in two stages - creation of a qpdf_data + * object and writing of the qpdf_data object. This allows the qpdf_data object to be modified + * prior to writing it out. See examples/qpdfjob-remove-annotations for a C++ illustration of + * its use. + * + * This function wraps QPDFJob::createQPDF. It runs the first stage of the job. A nullptr is + * returned if the job did not produce any pdf file to be written. + */ + QPDF_DLL + qpdf_data qpdfjob_create_qpdf(qpdfjob_handle j); + + /* This function wraps QPDFJob::writeQPDF. It returns the error code that qpdf would return with + * the equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. NOTE it is the callers responsibility to clean up the resources + * associated with the qpdf_data object by calling qpdf_cleanup after the call to + * qpdfjob_write_qpdf. + */ + QPDF_DLL + int qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf); + + /* Allow specification of a custom progress reporter. The progress reporter is only used if + * progress is otherwise requested (with the --progress option or "progress": "" in the JSON). + */ + QPDF_DLL + void qpdfjob_register_progress_reporter( + qpdfjob_handle j, void (*report_progress)(int percent, void* data), void* data); + +#ifdef __cplusplus +} +#endif + +#endif /* QPDFJOB_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdflogger-c.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdflogger-c.h new file mode 100644 index 0000000..b3d706a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/qpdf/qpdflogger-c.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFLOGGER_H +#define QPDFLOGGER_H + +/* + * This file provides a C API for QPDFLogger. See QPDFLogger.hh for information about the logger and + * examples/qpdfjob-c-save-attachment.c for an example. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /* To operate on a logger, you need a handle to it. call qpdflogger_default_logger to get a + * handle for the default logger. There are functions in qpdf-c.h and qpdfjob-c.h that also take + * or return logger handles. When you're done with the logger handler, call qpdflogger_cleanup. + * This cleans up the handle but leaves the underlying log object intact. (It uses a shared + * pointer and will be cleaned up automatically when it is no longer in use.) That means you can + * create a logger with qpdflogger_create(), pass the logger handle to a function in qpdf-c.h or + * qpdfjob-c.h, and then clean it up, subject to constraints imposed by the other function. + */ + + typedef struct _qpdflogger_handle* qpdflogger_handle; + QPDF_DLL + qpdflogger_handle qpdflogger_default_logger(); + + /* Calling cleanup on the handle returned by qpdflogger_create destroys the handle but not the + * underlying logger. See comments above. + */ + QPDF_DLL + qpdflogger_handle qpdflogger_create(); + + QPDF_DLL + void qpdflogger_cleanup(qpdflogger_handle* l); + + enum qpdf_log_dest_e { + qpdf_log_dest_default = 0, + qpdf_log_dest_stdout = 1, + qpdf_log_dest_stderr = 2, + qpdf_log_dest_discard = 3, + qpdf_log_dest_custom = 4, + }; + + /* Function should return 0 on success. */ + typedef int (*qpdf_log_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + void qpdflogger_set_info( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_warn( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_error( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + + /* A non-zero value for only_if_not_set means that the save pipeline will only be changed if it + * is not already set. + */ + QPDF_DLL + void qpdflogger_set_save( + qpdflogger_handle l, + enum qpdf_log_dest_e dest, + qpdf_log_fn_t fn, + void* udata, + int only_if_not_set); + QPDF_DLL + void qpdflogger_save_to_standard_output(qpdflogger_handle l, int only_if_not_set); + + /* For testing */ + QPDF_DLL + int qpdflogger_equal(qpdflogger_handle l1, qpdflogger_handle l2); + +#ifdef __cplusplus +} +#endif + +#endif // QPDFLOGGER_H diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/turbojpeg.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/turbojpeg.h new file mode 100644 index 0000000..9255aee --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/turbojpeg.h @@ -0,0 +1,2923 @@ +/* + * Copyright (C) 2009-2015, 2017, 2020-2026 D. R. Commander + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TURBOJPEG_H__ +#define __TURBOJPEG_H__ + +#include + +#define TURBOJPEG_VERSION_NUMBER 3002000 + +#if defined(_WIN32) && defined(DLLDEFINE) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +#define DLLCALL + + +/** + * @addtogroup TurboJPEG + * TurboJPEG API. This API provides an interface for generating, decoding, and + * transforming planar YUV and JPEG images in memory. + * + * @anchor YUVnotes + * YUV Image Format Notes + * ---------------------- + * Technically, the JPEG format uses the YCbCr colorspace (which is technically + * not a colorspace but a color transform), but per the convention of the + * digital video community, the TurboJPEG API uses "YUV" to refer to an image + * format consisting of Y, Cb, and Cr image planes. + * + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (1 in the case of 4:4:4, grayscale, 4:4:0, or 4:4:1; 2 in + * the case of 4:2:2, 4:2:0, or 2:4; 4 in the case of 4:1:1 or 4:1:0.) + * Similarly, the luminance plane height is the image height padded to the + * nearest multiple of the vertical subsampling factor (1 in the case of 4:4:4, + * 4:2:2, grayscale, or 4:1:1; 2 in the case of 4:2:0, 4:4:0, or 4:1:0; 4 in + * the case of 4:4:1 or 2:4.) This is irrespective of any additional padding + * that may be specified as an argument to the various YUV functions. The + * chrominance plane width is equal to the luminance plane width divided by the + * horizontal subsampling factor, and the chrominance plane height is equal to + * the luminance plane height divided by the vertical subsampling factor. + * + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a row alignment + * of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, + * and each of the chrominance planes would be 20 x 35 bytes. + * + * @{ + */ + + +/** + * The number of initialization options + */ +#define TJ_NUMINIT 3 + +/** + * Initialization options + */ +enum TJINIT { + /** + * Initialize the TurboJPEG instance for compression. + */ + TJINIT_COMPRESS, + /** + * Initialize the TurboJPEG instance for decompression. + */ + TJINIT_DECOMPRESS, + /** + * Initialize the TurboJPEG instance for lossless transformation (both + * compression and decompression.) + */ + TJINIT_TRANSFORM +}; + + +/** + * The number of chrominance subsampling options + */ +#define TJ_NUMSAMP 9 + +/** + * Chrominance subsampling options + * + * When pixels are converted from RGB to YCbCr (see #TJCS_YCbCr) or from CMYK + * to YCCK (see #TJCS_YCCK) as part of the JPEG compression process, some of + * the Cb and Cr (chrominance) components can be discarded or averaged together + * to produce a smaller image with little perceptible loss of image quality. + * (The human eye is more sensitive to small changes in brightness than to + * small changes in color.) This is called "chrominance subsampling". + */ +enum TJSAMP { + /** + * 4:4:4 chrominance subsampling (no chrominance subsampling) + * + * The JPEG or YUV image will contain one chrominance component for every + * pixel in the source image. + */ + TJSAMP_444, + /** + * 4:2:2 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x1 + * block of pixels in the source image. + */ + TJSAMP_422, + /** + * 4:2:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x2 + * block of pixels in the source image. + */ + TJSAMP_420, + /** + * Grayscale + * + * The JPEG or YUV image will contain no chrominance components. + */ + TJSAMP_GRAY, + /** + * 4:4:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x2 + * block of pixels in the source image. + * + * @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_440, + /** + * 4:1:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x1 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:1:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:1:1 is + * better able to reproduce sharp horizontal features. + * + * @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_411, + /** + * 4:4:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x4 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:4:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:4:1 is + * better able to reproduce sharp vertical features. + * + * @note 4:4:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_441, + /** + * 4:1:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x2 + * block of pixels in the source image. 4:1:0 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 4:1:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_410, + /** + * 2:4 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x4 + * block of pixels in the source image. 2:4 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 2:4 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_24, + /** + * Unknown subsampling + * + * The JPEG image uses an unusual type of chrominance subsampling. Such + * images can be decompressed into packed-pixel images, but they cannot be + * - decompressed into planar YUV images, + * - losslessly transformed if #TJXOPT_CROP is specified and #TJXOPT_GRAY is + * not specified, or + * - partially decompressed using a cropping region. + */ + TJSAMP_UNKNOWN = -1 +}; + +/** + * iMCU width (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUWidth[TJ_NUMSAMP] = { 8, 16, 16, 8, 8, 32, 8, 32, 16 }; + +/** + * iMCU height (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUHeight[TJ_NUMSAMP] = { 8, 8, 16, 8, 16, 8, 32, 16, 32 }; + + +/** + * The number of pixel formats + */ +#define TJ_NUMPF 12 + +/** + * Pixel formats + */ +enum TJPF { + /** + * RGB pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. + */ + TJPF_RGB, + /** + * BGR pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. + */ + TJPF_BGR, + /** + * RGBX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_RGBX, + /** + * BGRX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_BGRX, + /** + * XBGR pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XBGR, + /** + * XRGB pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XRGB, + /** + * Grayscale pixel format + * + * Each 1-sample pixel represents a luminance (brightness) level from 0 to + * the maximum sample value (which is, for instance, 255 for 8-bit samples or + * 4095 for 12-bit samples or 65535 for 16-bit samples.) + */ + TJPF_GRAY, + /** + * RGBA pixel format + * + * This is the same as @ref TJPF_RGBX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_RGBA, + /** + * BGRA pixel format + * + * This is the same as @ref TJPF_BGRX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_BGRA, + /** + * ABGR pixel format + * + * This is the same as @ref TJPF_XBGR, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ABGR, + /** + * ARGB pixel format + * + * This is the same as @ref TJPF_XRGB, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ARGB, + /** + * CMYK pixel format + * + * Unlike RGB, which is an additive color model used primarily for display, + * CMYK (Cyan/Magenta/Yellow/Key) is a subtractive color model used primarily + * for printing. In the CMYK color model, the value of each color component + * typically corresponds to an amount of cyan, magenta, yellow, or black ink + * that is applied to a white background. In order to convert between CMYK + * and RGB, it is necessary to use a color management system (CMS.) A CMS + * will attempt to map colors within the printer's gamut to perceptually + * similar colors in the display's gamut and vice versa, but the mapping is + * typically not 1:1 or reversible, nor can it be defined with a simple + * formula. Thus, such a conversion is out of scope for a codec library. + * However, the TurboJPEG API allows for compressing packed-pixel CMYK images + * into YCCK JPEG images (see #TJCS_YCCK) and decompressing YCCK JPEG images + * into packed-pixel CMYK images. + */ + TJPF_CMYK, + /** + * Unknown pixel format + * + * Currently this is only used by #tj3LoadImage8(), #tj3LoadImage12(), and + * #tj3LoadImage16(). + */ + TJPF_UNKNOWN = -1 +}; + +/** + * Red offset (in samples) for a given pixel format + * + * This specifies the number of samples that the red component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the red + * component is `pixel[tjRedOffset[TJPF_BGRX]]`. The offset is -1 if the pixel + * format does not have a red component. + */ +static const int tjRedOffset[TJ_NUMPF] = { + 0, 2, 0, 2, 3, 1, -1, 0, 2, 3, 1, -1 +}; +/** + * Green offset (in samples) for a given pixel format + * + * This specifies the number of samples that the green component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the green + * component is `pixel[tjGreenOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a green component. + */ +static const int tjGreenOffset[TJ_NUMPF] = { + 1, 1, 1, 1, 2, 2, -1, 1, 1, 2, 2, -1 +}; +/** + * Blue offset (in samples) for a given pixel format + * + * This specifies the number of samples that the blue component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the blue + * component is `pixel[tjBlueOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a blue component. + */ +static const int tjBlueOffset[TJ_NUMPF] = { + 2, 0, 2, 0, 1, 3, -1, 2, 0, 1, 3, -1 +}; +/** + * Alpha offset (in samples) for a given pixel format + * + * This specifies the number of samples that the alpha component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRA is stored in `unsigned char pixel[]`, then the alpha + * component is `pixel[tjAlphaOffset[TJPF_BGRA]]`. The offset is -1 if the + * pixel format does not have an alpha component. + */ +static const int tjAlphaOffset[TJ_NUMPF] = { + -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; +/** + * Pixel size (in samples) for a given pixel format + */ +static const int tjPixelSize[TJ_NUMPF] = { + 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4 +}; + + +/** + * The number of JPEG colorspaces + */ +#define TJ_NUMCS 5 + +/** + * JPEG colorspaces + */ +enum TJCS { + /** + * RGB colorspace + * + * When generating the JPEG image, the R, G, and B components in the source + * image are reordered into image planes, but no colorspace conversion or + * subsampling is performed. RGB JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats, but they cannot be generated from or + * decompressed to planar YUV images. + */ + TJCS_RGB, + /** + * YCbCr colorspace + * + * YCbCr is not an absolute colorspace but rather a mathematical + * transformation of RGB designed solely for storage and transmission. YCbCr + * images must be converted to RGB before they can be displayed. In the + * YCbCr colorspace, the Y (luminance) component represents the black & white + * portion of the original image, and the Cb and Cr (chrominance) components + * represent the color portion of the original image. Historically, the + * analog equivalent of this transformation allowed the same signal to be + * displayed to both black & white and color televisions, but JPEG images + * primarily use YCbCr because it optionally allows the color data to be + * subsampled in order to reduce network and disk usage. YCbCr is the most + * common JPEG colorspace, and YCbCr JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats. YCbCr JPEG images can also be generated from + * and decompressed to planar YUV images. + */ + TJCS_YCbCr, + /** + * Grayscale colorspace + * + * The JPEG image retains only the luminance data (Y component), and any + * color data from the source image is discarded. Grayscale JPEG images can + * be generated from and decompressed to packed-pixel images with any of the + * extended RGB or grayscale pixel formats, or they can be generated from + * and decompressed to planar YUV images. + */ + TJCS_GRAY, + /** + * CMYK colorspace + * + * When generating the JPEG image, the C, M, Y, and K components in the + * source image are reordered into image planes, but no colorspace conversion + * or subsampling is performed. CMYK JPEG images can only be generated from + * and decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_CMYK, + /** + * YCCK colorspace + * + * YCCK (AKA "YCbCrK") is not an absolute colorspace but rather a + * mathematical transformation of CMYK designed solely for storage and + * transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + * reversibly transformed into YCCK, and as with YCbCr, the chrominance + * components in the YCCK pixels can be subsampled without incurring major + * perceptual loss. YCCK JPEG images can only be generated from and + * decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_YCCK, + /** + * Default colorspace + * + * Generate a grayscale JPEG image if #TJPARAM_SUBSAMP is set to + * #TJSAMP_GRAY, a YCCK JPEG image if the source image is CMYK, and a YCbCr + * JPEG image otherwise. + */ + TJCS_DEFAULT = -1 +}; + + +/** + * Parameters + */ +enum TJPARAM { + /** + * Error handling behavior + * + * **Value** + * - `0` *[default]* Allow the current compression/decompression/transform + * operation to complete unless a fatal error is encountered. + * - `1` Immediately discontinue the current + * compression/decompression/transform operation if a warning (non-fatal + * error) occurs. + */ + TJPARAM_STOPONWARNING, + /** + * Row order in packed-pixel source/destination images + * + * **Value** + * - `0` *[default]* top-down (X11) order + * - `1` bottom-up (Windows, OpenGL) order + */ + TJPARAM_BOTTOMUP, + /** + * JPEG destination buffer (re)allocation [compression, lossless + * transformation] + * + * **Value** + * - `0` *[default]* Attempt to allocate or reallocate the JPEG destination + * buffer as needed. + * - `1` Generate an error if the JPEG destination buffer is invalid or too + * small. + */ + TJPARAM_NOREALLOC, + /** + * Perceptual quality of lossy JPEG images [compression only] + * + * **Value** + * - `1`-`100` (`1` = worst quality but best compression, `100` = best + * quality but worst compression) *[no default; must be explicitly + * specified]* + */ + TJPARAM_QUALITY, + /** + * Chrominance subsampling level + * + * The JPEG or YUV image uses (decompression, decoding) or will use (lossy + * compression, encoding) the specified level of chrominance subsampling. + * + * **Value** + * - One of the @ref TJSAMP "chrominance subsampling options" *[no default; + * must be explicitly specified for lossy compression, encoding, and + * decoding]* + */ + TJPARAM_SUBSAMP, + /** + * JPEG width (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGWIDTH, + /** + * JPEG height (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGHEIGHT, + /** + * Data precision (bits per sample) + * + * The JPEG image uses (decompression) or will use (lossless compression) the + * specified number of bits per sample. This parameter also specifies the + * target data precision when loading a PNG or PBMPLUS file with + * #tj3LoadImage8(), #tj3LoadImage12(), or #tj3LoadImage16() and the source + * data precision when saving a PNG or PBMPLUS file with #tj3SaveImage8(), + * #tj3SaveImage12(), or #tj3SaveImage16(). + * + * The data precision is the number of bits in the maximum sample value, + * which may not be the same as the width of the data type used to store the + * sample. + * + * **Value** + * - `8` or `12` for lossy JPEG images; `2` to `16` for lossless JPEG, PNG, + * and PBMPLUS images + * + * 12-bit JPEG data precision implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is set. + */ + TJPARAM_PRECISION, + /** + * JPEG colorspace + * + * The JPEG image uses (decompression) or will use (lossy compression) the + * specified colorspace. + * + * **Value** + * - One of the @ref TJCS "JPEG colorspaces" *[default for lossy compression: + * automatically selected based on the subsampling level and pixel format]* + */ + TJPARAM_COLORSPACE, + /** + * Chrominance upsampling algorithm [lossy decompression only] + * + * **Value** + * - `0` *[default]* Use smooth upsampling when decompressing a JPEG image + * that was generated using 4:2:2, 4:2:0, or 4:4:0 chrominance subsampling. + * This creates a smooth transition between neighboring chrominance + * components in order to reduce upsampling artifacts in the decompressed + * image. + * - `1` Use the fastest chrominance upsampling algorithm available, which + * may combine upsampling with color conversion. + */ + TJPARAM_FASTUPSAMPLE, + /** + * DCT/IDCT algorithm [lossy compression and decompression] + * + * **Value** + * - `0` *[default]* Use the most accurate DCT/IDCT algorithm available. + * - `1` Use the fastest DCT/IDCT algorithm available. + * + * This parameter is provided mainly for backward compatibility with libjpeg, + * which historically implemented several different DCT/IDCT algorithms + * because of performance limitations with 1990s CPUs. In the libjpeg-turbo + * implementation of the TurboJPEG API: + * - The "fast" and "accurate" DCT/IDCT algorithms perform similarly on + * modern x86/x86-64 CPUs that support AVX2 instructions. + * - The "fast" algorithm is generally only about 5-15% faster than the + * "accurate" algorithm on other types of CPUs. + * - The difference in accuracy between the "fast" and "accurate" algorithms + * is the most pronounced at JPEG quality levels above 90 and tends to be + * more pronounced with decompression than with compression. + * - For JPEG quality levels above 97, the "fast" algorithm degrades and is + * not fully accelerated, so it is slower than the "accurate" algorithm. + */ + TJPARAM_FASTDCT, + /** + * Huffman table optimization [lossy compression, lossless transformation] + * + * **Value** + * - `0` *[default]* The JPEG image will use the default Huffman tables. + * - `1` Optimal Huffman tables will be computed for the JPEG image. For + * lossless transformation, this can also be specified using + * #TJXOPT_OPTIMIZE. + * + * Huffman table optimization improves compression slightly (generally 5% or + * less), but it reduces compression performance considerably. + */ + TJPARAM_OPTIMIZE, + /** + * Progressive JPEG + * + * In a progressive JPEG image, the DCT coefficients are split across + * multiple "scans" of increasing quality. Thus, a low-quality scan + * containing the lowest-frequency DCT coefficients can be transmitted first + * and refined with subsequent higher-quality scans containing + * higher-frequency DCT coefficients. When using Huffman entropy coding, the + * progressive JPEG format also provides an "end-of-bands (EOB) run" feature + * that allows large groups of zeroes, potentially spanning multiple MCUs, + * to be represented using only a few bytes. + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image is (decompression) or will be (compression, lossless transformation) + * single-scan. + * - `1` The lossy JPEG image is (decompression) or will be (compression, + * lossless transformation) progressive. For lossless transformation, this + * can also be specified using #TJXOPT_PROGRESSIVE. + * + * Progressive JPEG images generally have better compression ratios than + * single-scan JPEG images (much better if the image has large areas of solid + * color), but progressive JPEG compression and decompression is considerably + * slower than single-scan JPEG compression and decompression. Can be + * combined with #TJPARAM_ARITHMETIC. Implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is also set. + */ + TJPARAM_PROGRESSIVE, + /** + * Progressive JPEG scan limit for lossy JPEG images [decompression, lossless + * transformation] + * + * Setting this parameter causes the decompression and transform functions to + * return an error if the number of scans in a progressive JPEG image exceeds + * the specified limit. The primary purpose of this is to allow + * security-critical applications to guard against an exploit of the + * progressive JPEG format described in + * this report. + * + * **Value** + * - maximum number of progressive JPEG scans that the decompression and + * transform functions will process *[default: `0` (no limit)]* + * + * @see #TJPARAM_PROGRESSIVE + */ + TJPARAM_SCANLIMIT, + /** + * Arithmetic entropy coding + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image uses (decompression) or will use (compression, lossless + * transformation) Huffman entropy coding. + * - `1` The lossy JPEG image uses (decompression) or will use (compression, + * lossless transformation) arithmetic entropy coding. For lossless + * transformation, this can also be specified using #TJXOPT_ARITHMETIC. + * + * Arithmetic entropy coding generally improves compression relative to + * Huffman entropy coding, but it reduces compression and decompression + * performance considerably. Can be combined with #TJPARAM_PROGRESSIVE. + */ + TJPARAM_ARITHMETIC, + /** + * Lossless JPEG + * + * **Value** + * - `0` *[default for compression]* The JPEG image is (decompression) or + * will be (compression) lossy/DCT-based. + * - `1` The JPEG image is (decompression) or will be (compression) + * lossless/predictive. + * + * In most cases, lossless JPEG compression and decompression is considerably + * slower than lossy JPEG compression and decompression, and lossless JPEG + * images are much larger than lossy JPEG images. Thus, lossless JPEG images + * are typically used only for applications that require mathematically + * lossless compression. Also note that the following features are not + * available with lossless JPEG images: + * - Colorspace conversion (lossless JPEG images always use #TJCS_RGB, + * #TJCS_GRAY, or #TJCS_CMYK, depending on the pixel format of the source + * image) + * - Chrominance subsampling (lossless JPEG images always use #TJSAMP_444) + * - JPEG quality selection + * - DCT/IDCT algorithm selection + * - Progressive JPEG + * - Arithmetic entropy coding + * - Compression from/decompression to planar YUV images (this parameter is + * ignored by #tj3CompressFromYUV8() and #tj3CompressFromYUVPlanes8()) + * - Decompression scaling + * - Lossless transformation + * + * @see #TJPARAM_LOSSLESSPSV, #TJPARAM_LOSSLESSPT + */ + TJPARAM_LOSSLESS, + /** + * Lossless JPEG predictor selection value (PSV) + * + * **Value** + * - `1`-`7` *[default for compression: `1`]* + * + * Lossless JPEG compression shares no algorithms with lossy JPEG + * compression. Instead, it uses differential pulse-code modulation (DPCM), + * an algorithm whereby each sample is encoded as the difference between the + * sample's value and a "predictor", which is based on the values of + * neighboring samples. If Ra is the sample immediately to the left of the + * current sample, Rb is the sample immediately above the current sample, and + * Rc is the sample diagonally to the left and above the current sample, then + * the relationship between the predictor selection value and the predictor + * is as follows: + * + * PSV | Predictor + * ----|---------- + * 1 | Ra + * 2 | Rb + * 3 | Rc + * 4 | Ra + Rb – Rc + * 5 | Ra + (Rb – Rc) / 2 + * 6 | Rb + (Ra – Rc) / 2 + * 7 | (Ra + Rb) / 2 + * + * Predictors 1-3 are 1-dimensional predictors, whereas Predictors 4-7 are + * 2-dimensional predictors. The best predictor for a particular image + * depends on the image. + * + * @see #TJPARAM_LOSSLESS + */ + TJPARAM_LOSSLESSPSV, + /** + * Lossless JPEG point transform (Pt) + * + * **Value** + * - `0` through ***precision*** *- 1*, where ***precision*** is the JPEG + * data precision in bits *[default for compression: `0`]* + * + * A point transform value of `0` is necessary in order to generate a fully + * lossless JPEG image. (A non-zero point transform value right-shifts the + * input samples by the specified number of bits, which is effectively a form + * of lossy color quantization.) + * + * @see #TJPARAM_LOSSLESS, #TJPARAM_PRECISION + */ + TJPARAM_LOSSLESSPT, + /** + * JPEG restart marker interval in MCUs [lossy compression, + * lossless transformation] + * + * The nature of entropy coding is such that a corrupt JPEG image cannot + * be decompressed beyond the point of corruption unless it contains restart + * markers. A restart marker stops and restarts the entropy coding algorithm + * so that, if a JPEG image is corrupted, decompression can resume at the + * next marker. Thus, adding more restart markers improves the fault + * tolerance of the JPEG image, but adding too many restart markers can + * adversely affect the compression ratio and performance. + * + * In typical JPEG images, an MCU (Minimum Coded Unit) is the minimum set of + * interleaved "data units" (8x8 DCT blocks if the image is lossy or samples + * if the image is lossless) necessary to represent at least one data unit + * per component. (For example, an MCU in an interleaved lossy JPEG image + * that uses 4:2:2 subsampling consists of two luminance blocks followed by + * one block for each chrominance component.) In single-component or + * non-interleaved JPEG images, an MCU is the same as a data unit. + * + * **Value** + * - the number of MCUs between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTROWS to 0. + */ + TJPARAM_RESTARTBLOCKS, + /** + * JPEG restart marker interval in MCU rows [compression, + * lossless transformation] + * + * See #TJPARAM_RESTARTBLOCKS for a description of restart markers and MCUs. + * An MCU row is a row of MCUs spanning the entire width of the image. + * + * **Value** + * - the number of MCU rows between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTBLOCKS to + * 0. + */ + TJPARAM_RESTARTROWS, + /** + * JPEG horizontal pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified horizontal pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_XDENSITY, + /** + * JPEG vertical pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified vertical pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_YDENSITY, + /** + * JPEG pixel density units + * + * **Value** + * - `0` *[default for compression]* The pixel density of the JPEG image is + * expressed (decompression) or will be expressed (compression) in unknown + * units. + * - `1` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/inch. + * - `2` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/cm. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_XDENSITY, TJPARAM_YDENSITY + */ + TJPARAM_DENSITYUNITS, + /** + * Memory limit for intermediate buffers + * + * **Value** + * - the maximum amount of memory (in megabytes) that will be allocated for + * intermediate buffers, which are used with progressive JPEG compression and + * decompression, Huffman table optimization, lossless JPEG compression, and + * lossless transformation *[default: `0` (no limit)]* + */ + TJPARAM_MAXMEMORY, + /** + * Image size limit [decompression, lossless transformation, packed-pixel + * image loading] + * + * Setting this parameter causes the decompression, transform, and image + * loading functions to return an error if the number of pixels in the source + * image exceeds the specified limit. This allows security-critical + * applications to guard against excessive memory consumption. + * + * **Value** + * - maximum number of pixels that the decompression, transform, and image + * loading functions will process *[default: `0` (no limit)]* + */ + TJPARAM_MAXPIXELS, + /** + * Marker copying behavior [decompression, lossless transformation, + * packed-pixel image I/O] + * + * **Value [lossless transformation]** + * - `0` Do not copy any extra markers (including comments, JFIF thumbnails, + * Exif data, and ICC profile data) from the source image to the destination + * image. + * - `1` Do not copy any extra markers, except comment (COM) markers, from + * the source image to the destination image. + * - `2` *[default]* Copy all extra markers from the source image to the + * destination image. + * - `3` Copy all extra markers, except ICC profile data (APP2 markers), from + * the source image to the destination image. + * - `4` Do not copy any extra markers, except ICC profile data (APP2 + * markers), from the source image to the destination image. + * + * #TJXOPT_COPYNONE overrides this parameter for a particular transform. + * This parameter overrides any ICC profile that was previously associated + * with the TurboJPEG instance using #tj3SetICCProfile(), #tj3LoadImage8(), + * #tj3LoadImage12(), or #tj3LoadImage16(). + * + * If this parameter is set to `2` or `4`: + * - When decompressing, #tj3DecompressHeader() extracts the ICC profile from + * a JPEG image. #tj3GetICCProfile() can then be used to retrieve the + * profile. + * - When loading a PNG image using a TurboJPEG compression instance, + * #tj3LoadImage8(), #tj3LoadImage12(), and #tj3LoadImage16() extract the + * ICC profile from the PNG image and associate the profile with the + * TurboJPEG instance. #tj3GetICCProfile() can then be used to retrieve + * the profile. + * - When saving a PNG image using a TurboJPEG decompression instance, + * #tj3SaveImage8(), #tj3SaveImage12(), and #tj3SaveImage16() transfer the + * ICC profile that was previously extracted from a JPEG image to the PNG + * image. + */ + TJPARAM_SAVEMARKERS +}; + + +/** + * The number of error codes + */ +#define TJ_NUMERR 2 + +/** + * Error codes + */ +enum TJERR { + /** + * The error was non-fatal and recoverable, but the destination image may + * still be corrupt. + */ + TJERR_WARNING, + /** + * The error was fatal and non-recoverable. + */ + TJERR_FATAL +}; + + +/** + * The number of transform operations + */ +#define TJ_NUMXOP 8 + +/** + * Transform operations for #tj3Transform() + */ +enum TJXOP { + /** + * Do not transform the position of the image pixels. + */ + TJXOP_NONE, + /** + * Flip (mirror) image horizontally. This transform is imperfect if there + * are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_HFLIP, + /** + * Flip (mirror) image vertically. This transform is imperfect if there are + * any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_VFLIP, + /** + * Transpose image (flip/mirror along upper left to lower right axis.) This + * transform is always perfect. + */ + TJXOP_TRANSPOSE, + /** + * Transverse transpose image (flip/mirror along upper right to lower left + * axis.) This transform is imperfect if there are any partial iMCUs in the + * image (see #TJXOPT_PERFECT.) + */ + TJXOP_TRANSVERSE, + /** + * Rotate image clockwise by 90 degrees. This transform is imperfect if + * there are any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT90, + /** + * Rotate image 180 degrees. This transform is imperfect if there are any + * partial iMCUs in the image (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT180, + /** + * Rotate image counter-clockwise by 90 degrees. This transform is imperfect + * if there are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT270 +}; + + +/** + * This option causes #tj3Transform() to return an error if the transform is + * not perfect. Lossless transforms operate on iMCUs, the size of which + * depends on the level of chrominance subsampling used (see #tjMCUWidth and + * #tjMCUHeight.) If the image's width or height is not evenly divisible by + * the iMCU size, then there will be partial iMCUs on the right and/or bottom + * edges. It is not possible to move these partial iMCUs to the top or left of + * the image, so any transform that would require that is "imperfect." If this + * option is not specified, then any partial iMCUs that cannot be transformed + * will be left in place, which will create odd-looking strips on the right or + * bottom edge of the image. + */ +#define TJXOPT_PERFECT (1 << 0) +/** + * Discard any partial iMCUs that cannot be transformed. + */ +#define TJXOPT_TRIM (1 << 1) +/** + * Enable lossless cropping. See #tj3Transform() for more information. + */ +#define TJXOPT_CROP (1 << 2) +/** + * Discard the color data in the source image, and generate a grayscale + * destination image. + */ +#define TJXOPT_GRAY (1 << 3) +/** + * Do not generate a destination image. (This can be used in conjunction with + * a custom filter to capture the transformed DCT coefficients without + * transcoding them.) + */ +#define TJXOPT_NOOUTPUT (1 << 4) +/** + * Generate a progressive destination image instead of a single-scan + * destination image. Progressive JPEG images generally have better + * compression ratios than single-scan JPEG images (much better if the image + * has large areas of solid color), but progressive JPEG decompression is + * considerably slower than single-scan JPEG decompression. Can be combined + * with #TJXOPT_ARITHMETIC. Implies #TJXOPT_OPTIMIZE unless #TJXOPT_ARITHMETIC + * is also specified. + */ +#define TJXOPT_PROGRESSIVE (1 << 5) +/** + * Do not copy any extra markers (including Exif and ICC profile data) from the + * source image to the destination image. + */ +#define TJXOPT_COPYNONE (1 << 6) +/** + * Enable arithmetic entropy coding in the destination image. Arithmetic + * entropy coding generally improves compression relative to Huffman entropy + * coding (the default), but it reduces decompression performance considerably. + * Can be combined with #TJXOPT_PROGRESSIVE. + */ +#define TJXOPT_ARITHMETIC (1 << 7) +/** + * Enable Huffman table optimization for the destination image. Huffman table + * optimization improves compression slightly (generally 5% or less.) + */ +#define TJXOPT_OPTIMIZE (1 << 8) + + +/** + * Scaling factor + */ +typedef struct { + /** + * Numerator + */ + int num; + /** + * Denominator + */ + int denom; +} tjscalingfactor; + +/** + * Cropping region + */ +typedef struct { + /** + * The left boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU width (see #tjMCUWidth) of the + * destination image. For decompression, this must be evenly divisible by + * the scaled iMCU width of the source image. + */ + int x; + /** + * The upper boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU height (see #tjMCUHeight) of the + * destination image. + */ + int y; + /** + * The width of the cropping region. Setting this to 0 is the equivalent of + * setting it to the width of the source JPEG image - x. + */ + int w; + /** + * The height of the cropping region. Setting this to 0 is the equivalent of + * setting it to the height of the source JPEG image - y. + */ + int h; +} tjregion; + +/** + * A #tjregion structure that specifies no cropping + */ +static const tjregion TJUNCROPPED = { 0, 0, 0, 0 }; + +/** + * Lossless transform + */ +typedef struct tjtransform { + /** + * Cropping region + */ + tjregion r; + /** + * One of the @ref TJXOP "transform operations" + */ + int op; + /** + * The bitwise OR of one of more of the @ref TJXOPT_ARITHMETIC + * "transform options" + */ + int options; + /** + * Arbitrary data that can be accessed within the body of the callback + * function + */ + void *data; + /** + * A callback function that can be used to modify the DCT coefficients after + * they are losslessly transformed but before they are transcoded to a new + * JPEG image. This allows for custom filters or other transformations to be + * applied in the frequency domain. + * + * @param coeffs pointer to an array of transformed DCT coefficients. (NOTE: + * This pointer is not guaranteed to be valid once the callback returns, so + * applications wishing to hand off the DCT coefficients to another function + * or library should make a copy of them within the body of the callback.) + * + * @param arrayRegion #tjregion structure containing the width and height of + * the array pointed to by `coeffs` as well as its offset relative to the + * component plane. TurboJPEG implementations may choose to split each + * component plane into multiple DCT coefficient arrays and call the callback + * function once for each array. + * + * @param planeRegion #tjregion structure containing the width and height of + * the component plane to which `coeffs` belongs + * + * @param componentID ID number of the component plane to which `coeffs` + * belongs. (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in + * typical JPEG images.) + * + * @param transformID ID number of the transformed image to which `coeffs` + * belongs. This is the same as the index of the transform in the + * `transforms` array that was passed to #tj3Transform(). + * + * @param transform a pointer to a #tjtransform structure that specifies the + * parameters and/or cropping region for this transform + * + * @return 0 if the callback was successful, or -1 if an error occurred. + */ + int (*customFilter) (short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentID, int transformID, + struct tjtransform *transform); +} tjtransform; + +/** + * TurboJPEG instance handle + */ +typedef void *tjhandle; + + +/** + * Compute the scaled value of `dimension` using the given scaling factor. + * This macro performs the integer equivalent of `ceil(dimension * + * scalingFactor)`. + */ +#define TJSCALED(dimension, scalingFactor) \ + (((dimension) * scalingFactor.num + scalingFactor.denom - 1) / \ + scalingFactor.denom) + +/** + * A #tjscalingfactor structure that specifies a scaling factor of 1/1 (no + * scaling) + */ +static const tjscalingfactor TJUNSCALED = { 1, 1 }; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Create a new TurboJPEG instance. + * + * @param initType one of the @ref TJINIT "initialization options" + * + * @return a handle to the newly-created instance, or NULL if an error occurred + * (see #tj3GetErrorStr().) + */ +#ifdef __DOXYGEN__ +DLLEXPORT tjhandle tj3Init(int initType); +#else +#define tj3Init(initType) tj3InitVersion(initType, TURBOJPEG_VERSION_NUMBER) +#endif + +DLLEXPORT tjhandle tj3InitVersion(int initType, int apiVersion); + + +/** + * Destroy a TurboJPEG instance. + * + * @param handle handle to a TurboJPEG instance. If the handle is NULL, then + * this function has no effect. + */ +DLLEXPORT void tj3Destroy(tjhandle handle); + + +/** + * Returns a descriptive error message explaining why the last command failed. + * + * @param handle handle to a TurboJPEG instance, or NULL if the error was + * generated by a global function (but note that retrieving the error message + * for a global function is thread-safe only on platforms that support + * thread-local storage.) + * + * @return a descriptive error message explaining why the last command failed. + */ +DLLEXPORT char *tj3GetErrorStr(tjhandle handle); + + +/** + * Returns a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + * + * @param handle handle to a TurboJPEG instance + * + * @return a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + */ +DLLEXPORT int tj3GetErrorCode(tjhandle handle); + + +/** + * Set the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @param value value of the parameter (refer to @ref TJPARAM + * "parameter documentation") + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3Set(tjhandle handle, int param, int value); + + +/** + * Get the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @return the value of the specified parameter, or -1 if the value is unknown. + */ +DLLEXPORT int tj3Get(tjhandle handle, int param); + + +/** + * Allocate a byte buffer for use with TurboJPEG. You should always use this + * function to allocate the JPEG destination buffer(s) for the compression and + * transform functions unless you are disabling automatic buffer (re)allocation + * (by setting #TJPARAM_NOREALLOC.) + * + * @param bytes the number of bytes to allocate + * + * @return a pointer to a newly-allocated buffer with the specified number of + * bytes. + * + * @see tj3Free() + */ +DLLEXPORT void *tj3Alloc(size_t bytes); + + +/** + * Free a byte buffer previously allocated by TurboJPEG. You should always use + * this function to free JPEG destination buffer(s) that were automatically + * (re)allocated by the compression and transform functions or that were + * manually allocated using #tj3Alloc(). + * + * @param buffer address of the buffer to free. If the address is NULL, then + * this function has no effect. + * + * @see tj3Alloc() + */ +DLLEXPORT void tj3Free(void *buffer); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image with + * the given parameters. The number of bytes returned by this function is + * larger than the size of the uncompressed source image. The reason for this + * is that the JPEG format uses 16-bit coefficients, so it is possible for a + * very high-quality source image with very high-frequency content to expand + * rather than compress when converted to the JPEG format. Such images + * represent very rare corner cases, but since there is no way to predict the + * size of a JPEG image prior to compression, the corner cases have to be + * handled. + * + * @param width width (in pixels) of the image + * + * @param height height (in pixels) of the image + * + * @param jpegSubsamp the level of chrominance subsampling to be used when + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) #TJSAMP_UNKNOWN is treated like + * #TJSAMP_444, since a buffer large enough to hold a JPEG image with no + * subsampling should also be large enough to hold a JPEG image with an + * arbitrary level of subsampling. Note that lossless JPEG images always + * use #TJSAMP_444. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * image, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3JPEGBufSize(int width, int height, int jpegSubsamp); + + +/** + * The size of the buffer (in bytes) required to hold a unified planar YUV + * image with the given parameters. + * + * @param width width (in pixels) of the image + * + * @param align row alignment (in bytes) of the image (must be a power of 2.) + * Setting this parameter to n specifies that each row in each plane of the + * image will be padded to the nearest multiple of n bytes (1 = unpadded.) + * + * @param height height (in pixels) of the image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the image, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVBufSize(int width, int align, int height, int subsamp); + + +/** + * The size of the buffer (in bytes) required to hold a YUV image plane with + * the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: This is the width of + * the whole image, not the plane width. + * + * @param stride bytes per row in the image plane. Setting this to 0 is the + * equivalent of setting it to the plane width. + * + * @param height height (in pixels) of the YUV image. NOTE: This is the height + * of the whole image, not the plane height. + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the YUV image + * plane, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVPlaneSize(int componentID, int width, int stride, + int height, int subsamp); + + +/** + * The plane width of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane width of a YUV image plane with the given parameters, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneWidth(int componentID, int width, int subsamp); + + +/** + * The plane height of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane height of a YUV image plane with the given parameters, or + * 0 if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneHeight(int componentID, int height, int subsamp); + + +/** + * Embed an ICC (International Color Consortium) color management profile in + * JPEG images generated by subsequent compression and lossless transformation + * operations. + * + * @note Lossless transformation operations ignore this ICC profile unless + * #TJXOPT_COPYNONE is specified or #TJPARAM_SAVEMARKERS is set to something + * other than `2` or `4`. Otherwise the ICC profile in the source image takes + * precedence, even if the source image has no ICC profile. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param iccBuf pointer to a byte buffer containing an ICC profile. A copy is + * made of the ICC profile, so this buffer can be freed or reused as soon as + * this function returns. Setting this parameter to NULL or setting `iccSize` + * to 0 removes any ICC profile that was previously associated with the + * TurboJPEG instance. + * + * @param iccSize size of the ICC profile (in bytes.) Setting this parameter + * to 0 or setting `iccBuf` to NULL removes any ICC profile that was previously + * associated with the TurboJPEG instance. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetICCProfile(tjhandle handle, unsigned char *iccBuf, + size_t iccSize); + + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 2 to 8 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 9 to 12 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress12(tjhandle handle, const short *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 13 to 16 bits of + * data precision per sample into a lossless JPEG image with the same data + * precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress16(tjhandle handle, const unsigned short *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Compress a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into + * an 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or + * @ref TJCS_GRAY "grayscale" JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if compressing a grayscale image) that contain a YUV + * source image to be compressed. These planes can be contiguous or + * non-contiguous in memory. The size of each plane should match the value + * returned by #tj3YUVPlaneSize() for the given image width, height, strides, + * and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer to + * @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to create a JPEG image from a subregion of a larger + * planar YUV image. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + int width, const int *strides, + int height, unsigned char **jpegBuf, + size_t *jpegSize); + + +/** + * Compress an 8-bit-per-sample unified planar YUV image into an + * 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or @ref TJCS_GRAY "grayscale" + * JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be compressed. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param align row alignment (in bytes) of the source image (must be a power + * of 2.) Setting this parameter to n indicates that each row in each plane of + * the source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUV8(tjhandle handle, + const unsigned char *srcBuf, int width, + int align, int height, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * color conversion and downsampling (which are accelerated in the + * libjpeg-turbo implementation) but does not execute any of the other steps in + * the JPEG compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if generating a grayscale image) that will receive the + * encoded image. These planes can be contiguous or non-contiguous in memory. + * Use #tj3YUVPlaneSize() to determine the appropriate size for each plane + * based on the image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the plane width (see @ref YUVnotes + * "YUV Image Format Notes".) If `strides` is NULL, then the strides for all + * planes will be set to their respective plane widths. You can adjust the + * strides in order to add an arbitrary amount of row padding to each plane or + * to encode an RGB or grayscale image into a subregion of a larger planar YUV + * image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUVPlanes8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into an + * 8-bit-per-sample unified planar YUV image. This function performs color + * conversion and downsampling (which are accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * image. Use #tj3YUVBufSize() to determine the appropriate size for this + * buffer based on the image width, height, row alignment, and level of + * chrominance subsampling (see #TJPARAM_SUBSAMP.) The Y, U (Cb), and V (Cr) + * image planes will be stored sequentially in the buffer. (Refer to + * @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align); + + +/** + * Retrieve information about a JPEG image without decompressing it, or prime + * the decompressor with quantization and Huffman tables. If a JPEG image is + * passed to this function, then the @ref TJPARAM "parameters" that describe + * the JPEG image will be set when the function returns. If a JPEG image is + * passed to this function and #TJPARAM_SAVEMARKERS is set to `2` or `4`, then + * the ICC profile (if any) will be extracted from the JPEG image. + * (#tj3GetICCProfile() can then be used to retrieve the profile.) + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing a JPEG image or an + * "abbreviated table specification" (AKA "tables-only") datastream. Passing a + * tables-only datastream to this function primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. + * + * @param jpegSize size of the JPEG image or tables-only datastream (in bytes) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressHeader(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize); + + +/** + * Retrieve the ICC (International Color Consortium) color management profile + * (if any) that was previously extracted from a JPEG image or associated with + * a TurboJPEG compression instance. + * + * @note To extract the ICC profile from a JPEG image, call + * #tj3DecompressHeader() with #TJPARAM_SAVEMARKERS set to `2` or `4`. + * + * @note To associate an ICC profile with a TurboJPEG compression instance, + * call #tj3SetICCProfile() or use #tj3LoadImage8(), #tj3LoadImage12(), or + * #tj3LoadImage16() to load a PNG image with #TJPARAM_SAVEMARKERS set to `2` + * or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param iccBuf address of a pointer to a byte buffer. Upon return: + * - If `iccBuf` is not NULL and there is an ICC profile to retrieve, then + * `*iccBuf` will point to a byte buffer containing the ICC profile. This + * buffer should be freed using #tj3Free(). + * - If `iccBuf` is not NULL and there is no ICC profile to retrieve, then + * `*iccBuf` will be NULL. + * - If `iccBuf` is NULL, then only the ICC profile size will be retrieved, and + * the ICC profile can be retrieved later. + * + * @param iccSize address of a size_t variable. Upon return, the variable will + * contain the ICC profile size (or 0 if there is no ICC profile to retrieve.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3GetICCProfile(tjhandle handle, unsigned char **iccBuf, + size_t *iccSize); + + +/** + * Returns a list of fractional scaling factors that the JPEG decompressor + * supports. + * + * @param numScalingFactors pointer to an integer variable that will receive + * the number of elements in the list + * + * @return a pointer to a list of fractional scaling factors, or NULL if an + * error is encountered (see #tj3GetErrorStr().) + */ +DLLEXPORT tjscalingfactor *tj3GetScalingFactors(int *numScalingFactors); + + +/** + * Set the scaling factor for subsequent lossy decompression operations. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param scalingFactor #tjscalingfactor structure that specifies a fractional + * scaling factor that the decompressor supports (see #tj3GetScalingFactors()), + * or #TJUNSCALED for no scaling. Decompression scaling is a function + * of the IDCT algorithm, so scaling factors are generally limited to multiples + * of 1/8. If the entire JPEG image will be decompressed, then the width and + * height of the scaled destination image can be determined by calling + * #TJSCALED() with the JPEG width and height (see #TJPARAM_JPEGWIDTH and + * #TJPARAM_JPEGHEIGHT) and the specified scaling factor. When decompressing + * into a planar YUV image, an intermediate buffer copy will be performed if + * the width or height of the scaled destination image is not an even multiple + * of the iMCU size (see #tjMCUWidth and #tjMCUHeight.) Note that + * decompression scaling is not available (and the specified scaling factor is + * ignored) when decompressing lossless JPEG images (see #TJPARAM_LOSSLESS), + * since the IDCT algorithm is not used with those images. Note also that + * #TJPARAM_FASTDCT is ignored when decompression scaling is enabled. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetScalingFactor(tjhandle handle, + tjscalingfactor scalingFactor); + + +/** + * Set the cropping region for partially decompressing a lossy JPEG image into + * a packed-pixel image + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param croppingRegion #tjregion structure that specifies a subregion of the + * JPEG image to decompress, or #TJUNCROPPED for no cropping. The + * left boundary of the cropping region must be evenly divisible by the scaled + * iMCU width-- #TJSCALED(#tjMCUWidth[subsamp], scalingFactor), where + * `subsamp` is the level of chrominance subsampling in the JPEG image (see + * #TJPARAM_SUBSAMP) and `scalingFactor` is the decompression scaling factor + * (see #tj3SetScalingFactor().) The cropping region should be specified + * relative to the scaled image dimensions. Unless `croppingRegion` is + * #TJUNCROPPED, the JPEG header must be read (see + * #tj3DecompressHeader()) prior to calling this function. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetCroppingRegion(tjhandle handle, tjregion croppingRegion); + + +/** + * Decompress a JPEG image with 2 to 8 bits of data precision per sample into a + * packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * The @ref TJPARAM "parameters" that describe the JPEG image will be set when + * this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel + * decompressed image. This buffer should normally be + * `pitch * destinationHeight` samples in size. However, you can also use this + * parameter to decompress into a specific region of a larger buffer. NOTE: + * If the JPEG image is lossy, then `destinationHeight` is either the scaled + * JPEG height (see #TJSCALED(), #TJPARAM_JPEGHEIGHT, and + * #tj3SetScalingFactor()) or the height of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationHeight` is the JPEG height. + * + * @param pitch samples per row in the destination image. Normally this should + * be set to destinationWidth * #tjPixelSize[pixelFormat], if the + * destination image should be unpadded. (Setting this parameter to 0 is the + * equivalent of setting it to + * destinationWidth * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decompress into a specific region of + * a larger buffer. NOTE: If the JPEG image is lossy, then `destinationWidth` + * is either the scaled JPEG width (see #TJSCALED(), #TJPARAM_JPEGWIDTH, and + * #tj3SetScalingFactor()) or the width of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationWidth` is the JPEG width. + * + * @param pixelFormat pixel format of the destination image (see @ref + * TJPF "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Decompress8(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned char *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a JPEG image with 9 to 12 bits of data precision per sample into + * a packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * + * @note This function can also be used to decompress an 8-bit-per-sample lossy + * JPEG image into a 12-bit-per-sample packed-pixel image. + * + * @note The JPEG format uses 16-bit DCT coefficients and computes those + * coefficients relative to an 8x8 DCT block. Thus, an 8-bit-per-sample JPEG + * image can preserve most of the signal from an underexposed + * higher-data-precision source image, provided that the data precision of the + * source image is retained in the compressor until the forward DCT stage. + * (Modern digital cameras typically do that, but note that libjpeg-turbo does + * not. Our solution for retaining higher data precision in the compressor is + * simply to generate a 12-bit-per-sample JPEG image.) + * + * @note It may be desirable to preserve as much of that signal as possible in + * the decompressor, to facilitate shadow recovery in the decompressed image. + * Thus, calling this function forces the decompressor to use the + * 12-bit-per-sample decompression pipeline even if the JPEG image has 8 bits + * of data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress12(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, short *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a lossless JPEG image with 13 to 16 bits of data precision per + * sample into a packed-pixel RGB, grayscale, or CMYK image with the same + * data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress16(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned short *dstBuf, + int pitch, int pixelFormat); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * JPEG decompression but leaves out the color conversion step, so a planar YUV + * image is generated instead of a packed-pixel image. The + * @ref TJPARAM "parameters" that describe the JPEG image will be set when this + * function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decompressing a grayscale image) that will receive + * the decompressed image. These planes can be contiguous or non-contiguous in + * memory. Use #tj3YUVPlaneSize() to determine the appropriate size for each + * plane based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), + * strides, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer + * to @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the scaled plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective scaled plane widths. + * You can adjust the strides in order to add an arbitrary amount of row + * padding to each plane or to decompress the JPEG image into a subregion of a + * larger planar YUV image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char **dstPlanes, + int *strides); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into an 8-bit-per-sample + * unified planar YUV image. This function performs JPEG decompression but + * leaves out the color conversion step, so a planar YUV image is generated + * instead of a packed-pixel image. The @ref TJPARAM "parameters" that + * describe the JPEG image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * decompressed image. Use #tj3YUVBufSize() to determine the appropriate size + * for this buffer based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes will be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUV8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char *dstBuf, int align); + + +/** + * Decode a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into an + * 8-bit-per-sample packed-pixel RGB or grayscale image. This function + * performs color conversion (which is accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decoding a grayscale image) that contain a YUV image + * to be decoded. These planes can be contiguous or non-contiguous in memory. + * The size of each plane should match the value returned by #tj3YUVPlaneSize() + * for the given image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to decode a subregion of a larger planar YUV image. + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + const int *strides, unsigned char *dstBuf, + int width, int pitch, int height, + int pixelFormat); + + +/** + * Decode an 8-bit-per-sample unified planar YUV image into an 8-bit-per-sample + * packed-pixel RGB or grayscale image. This function performs color + * conversion (which is accelerated in the libjpeg-turbo implementation) but + * does not execute any of the other steps in the JPEG decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be decoded. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * source buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV source image (must be a + * power of 2.) Setting this parameter to n indicates that each row in each + * plane of the YUV source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int align, unsigned char *dstBuf, int width, + int pitch, int height, int pixelFormat); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image + * transformed with the given transform parameters and/or cropping region. + * This function is a wrapper for #tj3JPEGBufSize() that takes into account + * cropping, transposition of the width and height (which affects the + * destination image dimensions and level of chrominance subsampling), + * grayscale conversion, and the ICC profile (if any) that was previously + * associated with the TurboJPEG instance or extracted from the source image + * (see #tj3SetICCProfile(), #tj3GetICCProfile(), and #TJPARAM_SAVEMARKERS.) + * The JPEG header must be read (see #tj3DecompressHeader()) prior to calling + * this function. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param transform pointer to a #tjtransform structure that specifies the + * transform parameters and/or cropping region for the JPEG image. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * transformed image, or 0 if an error occurred (see #tj3GetErrorStr() and + * #tj3GetErrorCode().) + */ +DLLEXPORT size_t tj3TransformBufSize(tjhandle handle, + const tjtransform *transform); + + +/** + * Losslessly transform a JPEG image into another JPEG image. Lossless + * transforms work by moving the raw DCT coefficients from one JPEG image + * structure to another without altering the values of the coefficients. While + * this is typically faster than decompressing the image, transforming it, and + * re-compressing it, lossless transforms are not free. Each lossless + * transform requires reading and performing entropy decoding on all of the + * coefficients in the source image, regardless of the size of the destination + * image. Thus, this function provides a means of generating multiple + * transformed images from the same source or applying multiple transformations + * simultaneously, in order to eliminate the need to read the source + * coefficients multiple times. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param jpegBuf pointer to a byte buffer containing the JPEG source image to + * transform + * + * @param jpegSize size of the JPEG source image (in bytes) + * + * @param n the number of transformed JPEG images to generate + * + * @param dstBufs pointer to an array of n byte buffers. `dstBufs[i]` will + * receive a JPEG image that has been transformed using the parameters in + * `transforms[i]`. TurboJPEG has the ability to reallocate the JPEG + * destination buffer to accommodate the size of the transformed JPEG image. + * Thus, you can choose to: + * -# pre-allocate the JPEG destination buffer with an arbitrary size using + * #tj3Alloc() and let TurboJPEG grow the buffer as needed, + * -# set `dstBufs[i]` to NULL to tell TurboJPEG to allocate the buffer for + * you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3TransformBufSize(). Under normal circumstances, this should ensure that + * the buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC + * guarantees that it won't be. However, if the source image has a large + * amount of embedded Exif data, then the transformed JPEG image may be larger + * than the worst-case size. #TJPARAM_NOREALLOC cannot be used in that case + * unless the embedded data is discarded using #TJXOPT_COPYNONE or + * #TJPARAM_SAVEMARKERS.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `dstBufs[i]` + * upon return from this function, as it may have changed. + * + * @param dstSizes pointer to an array of n size_t variables that will receive + * the actual sizes (in bytes) of each transformed JPEG image. If `dstBufs[i]` + * points to a pre-allocated buffer, then `dstSizes[i]` should be set to the + * size of the buffer. Otherwise, `dstSizes[i]` is ignored. Upon return, + * `dstSizes[i]` will contain the size of the transformed JPEG image (in + * bytes.) + * + * @param transforms pointer to an array of n #tjtransform structures, each of + * which specifies the transform parameters and/or cropping region for the + * corresponding transformed JPEG image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Transform(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, int n, unsigned char **dstBufs, + size_t *dstSizes, const tjtransform *transforms); + + +/** + * Load a packed-pixel image with 2 to 8 bits of data precision per sample from + * disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG, + * PBMPLUS (PPM/PGM), or Windows BMP format. Windows BMP files require + * 8-bit-per-sample data precision. When loading a PNG or PBMPLUS file, the + * target data precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. If the data precision of the PNG or PBMPLUS file does not match + * the target data precision, then upconverting or downconverting will be + * performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function varies depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files and 8-bit-per-pixel BMP files with a + * grayscale colormap can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned char *tj3LoadImage8(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 9 to 12 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 9 to 12 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 12 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT short *tj3LoadImage12(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 13 to 16 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 13 to 16 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 16 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned short *tj3LoadImage16(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + + +/** + * Save a packed-pixel image with 2 to 8 bits of data precision per sample from + * memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image. The + * image will be stored in PNG, PBMPLUS (PPM/PGM), or Windows BMP format, + * depending on the file extension. Windows BMP files require 8-bit-per-sample + * data precision. When saving a PNG or PBMPLUS file, the source data + * precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in grayscale PNG, PGM, or 8-bit-per-pixel (indexed + * color) BMP format. Otherwise, the image will be stored in truecolor PNG, + * PPM, or 24-bit-per-pixel BMP format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage8(tjhandle handle, const char *filename, + const unsigned char *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 9 to 12 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage12(tjhandle handle, const char *filename, + const short *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 13 to 16 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage16(tjhandle handle, const char *filename, + const unsigned short *buffer, int width, + int pitch, int height, int pixelFormat); + + +/* Backward compatibility functions and macros (nothing to see here) */ + +/* TurboJPEG 1.0+ */ + +#define NUMSUBOPT TJ_NUMSAMP +#define TJ_444 TJSAMP_444 +#define TJ_422 TJSAMP_422 +#define TJ_420 TJSAMP_420 +#define TJ_411 TJSAMP_420 +#define TJ_GRAYSCALE TJSAMP_GRAY + +#define TJ_BGR 1 +#define TJ_BOTTOMUP TJFLAG_BOTTOMUP +#define TJ_FORCEMMX TJFLAG_FORCEMMX +#define TJ_FORCESSE TJFLAG_FORCESSE +#define TJ_FORCESSE2 TJFLAG_FORCESSE2 +#define TJ_ALPHAFIRST 64 +#define TJ_FORCESSE3 TJFLAG_FORCESSE3 +#define TJ_FASTUPSAMPLE TJFLAG_FASTUPSAMPLE + +#define TJPAD(width) (((width) + 3) & (~3)) + +DLLEXPORT unsigned long TJBUFSIZE(int width, int height); + +DLLEXPORT int tjCompress(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, unsigned long *compressedSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelSize, + int flags); + +DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height); + +DLLEXPORT int tjDestroy(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr(void); + +DLLEXPORT tjhandle tjInitCompress(void); + +DLLEXPORT tjhandle tjInitDecompress(void); + +/* TurboJPEG 1.1+ */ + +#define TJ_YUV 512 + +DLLEXPORT unsigned long TJBUFSIZEYUV(int width, int height, int jpegSubsamp); + +DLLEXPORT int tjDecompressHeader2(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp); + +DLLEXPORT int tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int flags); + +DLLEXPORT int tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, int subsamp, int flags); + +/* TurboJPEG 1.2+ */ + +#define TJFLAG_BOTTOMUP 2 +#define TJFLAG_FORCEMMX 8 +#define TJFLAG_FORCESSE 16 +#define TJFLAG_FORCESSE2 32 +#define TJFLAG_FORCESSE3 128 +#define TJFLAG_FASTUPSAMPLE 256 +#define TJFLAG_NOREALLOC 1024 + +DLLEXPORT unsigned char *tjAlloc(int bytes); + +DLLEXPORT unsigned long tjBufSize(int width, int height, int jpegSubsamp); + +DLLEXPORT unsigned long tjBufSizeYUV(int width, int height, int subsamp); + +DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int subsamp, int flags); + +DLLEXPORT void tjFree(unsigned char *buffer); + +DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors); + +DLLEXPORT tjhandle tjInitTransform(void); + +DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, int n, + unsigned char **dstBufs, unsigned long *dstSizes, + tjtransform *transforms, int flags); + +/* TurboJPEG 1.2.1+ */ + +#define TJFLAG_FASTDCT 2048 +#define TJFLAG_ACCURATEDCT 4096 + +/* TurboJPEG 1.4+ */ + +DLLEXPORT unsigned long tjBufSizeYUV2(int width, int align, int height, + int subsamp); + +DLLEXPORT int tjCompressFromYUV(tjhandle handle, const unsigned char *srcBuf, + int width, int align, int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + int width, const int *strides, + int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, + int align, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjDecodeYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + const int *strides, int subsamp, + unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags); + +DLLEXPORT int tjDecompressHeader3(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp, + int *jpegColorspace); + +DLLEXPORT int tjDecompressToYUV2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int align, int height, int flags); + +DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, + unsigned char **dstPlanes, int width, + int *strides, int height, int flags); + +DLLEXPORT int tjEncodeYUV3(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align, int subsamp, + int flags); + +DLLEXPORT int tjEncodeYUVPlanes(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags); + +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); + +DLLEXPORT unsigned long tjPlaneSizeYUV(int componentID, int width, int stride, + int height, int subsamp); + +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp); + +/* TurboJPEG 2.0+ */ + +#define TJFLAG_STOPONWARNING 8192 +#define TJFLAG_PROGRESSIVE 16384 + +DLLEXPORT int tjGetErrorCode(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr2(tjhandle handle); + +DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, + int align, int *height, int *pixelFormat, + int flags); + +DLLEXPORT int tjSaveImage(const char *filename, unsigned char *buffer, + int width, int pitch, int height, int pixelFormat, + int flags); + +/* TurboJPEG 2.1+ */ + +#define TJFLAG_LIMITSCANS 32768 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zconf.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zconf.h new file mode 100644 index 0000000..1ff5e8c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zconf.h @@ -0,0 +1,555 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* #undef Z_PREFIX */ +#define HAVE_STDARG_H 1 +#define HAVE_UNISTD_H 1 + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compress_z z_compress_z +# define compress2_z z_compress2_z +# define compressBound z_compressBound +# define compressBound_z z_compressBound_z +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateBound_z z_deflateBound_z +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflateUsed z_deflateUsed +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define inflate_fixed z_inflate_fixed +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# define uncompress_z z_uncompress_z +# define uncompress2_z z_uncompress2_z +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#ifndef z_const +# ifdef ZLIB_CONST +# define z_const const +# else +# define z_const +# endif +#endif + +#ifdef Z_SOLO +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if HAVE_UNISTD_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if HAVE_STDARG_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# if defined(__WATCOMC__) || defined(__GO32__) || \ + (defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#elif defined(__MINGW32__) +# define z_off64_t long long +#elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +#elif defined(__GO32__) +# define z_off64_t offset_t +#else +# define z_off64_t z_off_t +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zlib.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zlib.h new file mode 100644 index 0000000..a57d336 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zlib.h @@ -0,0 +1,2057 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.3.2, February 17th, 2026 + + Copyright (C) 1995-2026 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 at https://datatracker.ietf.org/doc/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#ifdef ZLIB_BUILD +# include +#else +# include "zconf.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.3.2" +#define ZLIB_VERNUM 0x1320 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 2 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion(void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the input taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_RLE to limit match distances to one (run-length + encoding), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string + matching). Filtered data consists mostly of small values with a somewhat + random distribution, as produced by the PNG filters. In this case, the + compression algorithm is tuned to compress them better. The effect of + Z_FILTERED is to force more Huffman coding and less string matching than the + default; it is intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. + Z_RLE is almost as fast as Z_HUFFMAN_ONLY, but should give better + compression for PNG image data than Huffman only. The degree of string + matching from most to none is: Z_DEFAULT_STRATEGY, Z_FILTERED, Z_RLE, then + Z_HUFFMAN_ONLY. The strategy parameter affects the compression ratio but + never the correctness of the compressed output, even if it is not set + optimally for the given data. Z_FIXED uses the default string matching, but + prevents the use of dynamic Huffman codes, allowing for a simpler decoder + for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); +ZEXTERN z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. + + delfateBound_z() is the same, but takes and returns a size_t length. Note + that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. If an int is 16 bits and memLevel is 9, then + it is possible for the number of pending bytes to not fit in an unsigned. In + that case Z_BUF_ERROR is returned and *pending is set to the maximum value + of an unsigned. + */ + +ZEXTERN int ZEXPORT deflateUsed(z_streamp strm, + int *bits); +/* + deflateUsed() returns in *bits the most recent number of deflate bits used + in the last byte when flushing to a byte boundary. The result is in 1..8, or + 0 if there has not yet been a flush. This helps determine the location of + the last bit of a deflate stream. + + deflateUsed returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); +/* + This function inserts bits in the inflate input stream. The intent is to + use inflatePrime() to start inflating at a bit position in the middle of a + byte. The provided bits will be used before any bytes are used from + next_in. This function should be used with raw inflate, before the first + inflate() call, after inflateInit2() or inflateReset(). It can also be used + after an inflate() return indicates the end of a deflate block or header + when using Z_BLOCK. bits must be less than or equal to 16, and that many of + the least significant bits of value will be inserted in the input. The + other bits in value can be non-zero, and will be ignored. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent, or if bits is out of range. If inflate was + in the middle of processing a header, trailer, or stored block lengths, then + it is possible for there to be only eight bits available in the bit buffer. + In that case, bits > 8 is considered out of range. However, when used as + outlined above, there will always be 16 bits available in the buffer for + insertion. As noted in its documentation above, inflate records the number + of bits in the bit buffer on return in data_type. 32 minus that is the + number of bits available for insertion. inflatePrime does not update + data_type with the new number of bits in buffer. +*/ + +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) The extra, name, and comment pointers + much each be either Z_NULL or point to space to store that information from + the header. If extra is not Z_NULL, then extra_max contains the maximum + number of bytes that can be written to extra. Once done is true, extra_len + contains the actual extra field length, and extra contains the extra field, + or that field truncated if extra_max is less than extra_len. If name is not + Z_NULL, then up to name_max characters, including the terminating zero, are + written there. If comment is not Z_NULL, then up to comm_max characters, + including the terminating zero, are written there. The application can tell + that the name or comment did not fit in the provided space by the absence of + a terminating zero. If any of extra, name, or comment are not present in + the header, then that field's pointer is set to Z_NULL. This allows the use + of deflateSetHeader() with the returned structure to duplicate the header. + Note that if those fields initially pointed to allocated memory, then the + application will need to save them elsewhere so that they can be eventually + freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); + +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (all zeros is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() is not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + 27: 0 = gzprintf() present, 1 = not -- 1 means gzprintf() returns an error + + Remainder: + 28-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. The _z versions of the functions use the size_t + type for lengths. Note that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT compress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); +ZEXTERN int ZEXPORT compress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen, + int level); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); +ZEXTERN z_size_t ZEXPORT compressBound_z(z_size_t sourceLen); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT uncompress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. On entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) On exit, *destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); +ZEXTERN int ZEXPORT uncompress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. 'T' cannot be + used to force transparent reading. Transparent reading is automatically + performed if there is no gzip header at the start. Transparent reading can + be disabled with the 'G' option, which will instead return an error if there + is no gzip header. 'N' will open the file in non-blocking mode. + + 'a' can be used instead of 'w' to request that the gzip stream that will + be written be appended to the file. '+' will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + 'x' when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of 'e' when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. Note that if 'N' is in mode for non-blocking, the + open() itself can fail in order to not block. In that case gzopen() will + return NULL and errno will be EAGAIN or ENONBLOCK. The call to gzopen() can + then be re-tried. If the application would like to block on opening the + file, then it can use open() without O_NONBLOCK, and then gzdopen() with the + resulting file descriptor and 'N' in the mode, which will set it to non- + blocking. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. An + 'e' in mode will set fd's flag to close the file on an execve() call. An 'N' + in mode will set fd's non-blocking flag. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzread() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. If some data was read before an error, then that data is + returned until exhausted, after which the next call will signal the error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as that of fread() implementations in common libraries. This + could result in data loss if used with size != 1 when reading a concurrently + written file or a non-blocking file. In that case, use size == 1 or gzread() + instead. +*/ + +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written, or 0 in case of error or + if len is 0. If the write destination is non-blocking, then gzwrite() may + return a number of bytes written that is not 0 and less than len. + + If len does not fit in an int, then 0 is returned and nothing is written. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. + + If writing a concurrently read file or a non-blocking file with size != 1, + a partial item could be written, with no way of knowing how much of it was + not written, resulting in data loss. In that case, use size == 1 or + gzwrite() instead. +*/ + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); +#else +ZEXTERN int ZEXPORTVA gzprintf(); +#endif +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. + + In that last case, there may also be a buffer overflow with unpredictable + consequences, which is possible only if zlib was compiled with the insecure + functions sprintf() or vsprintf(), because the secure snprintf() and + vsnprintf() functions were not available. That would only be the case for + a non-ANSI C compiler. zlib may have been built without gzprintf() because + secure functions were not available and having gzprintf() be insecure was + not an option, in which case, gzprintf() returns Z_STREAM_ERROR. All of + these possibilities can be determined using zlibCompileFlags(). + + If a Z_BUF_ERROR is returned, then nothing was written due to a stall on + the non-blocking write destination. +*/ + +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. + The number of characters written may be less than the length of the string + if the write destination is non-blocking. + + If the length of the string does not fit in an int, then -1 is returned + and nothing is written. +*/ + +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If some data was read before an error, + then that data is returned until exhausted, after which the next call will + return NULL to signal the error. + + gzgets can be used on a file being concurrently written, and on a non- + blocking device, both as for gzread(). However lines may be broken in the + middle, leaving it up to the application to reassemble them as needed. +*/ + +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc(gzFile file); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 in + case of end of file or error. If some data was read before an error, then + that data is returned until exhausted, after which the next call will return + -1 to signal the error. + + This is implemented as a macro for speed. As such, it does not do all of + the checking the other functions do. I.e. it does not check to see if file + is NULL, nor whether the structure file points to has been clobbered or not. + + gzgetc can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzgetc() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. +*/ + +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). + + gzungetc(-1, file) will force any pending seek to execute. Then gztell() + will report the position, even if the requested seek reached end of file. + This can be used to determine the number of uncompressed bytes in a gzip + file without having to read it into a buffer. +*/ + +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. For reading or writing, any actual seeking is deferred + until the next read or write operation, or close operation when writing. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind(gzFile file); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof(gzFile file); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect(gzFile file); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). If the input is being written concurrently or the device is non- + blocking, then gzdirect() may give a different answer once four bytes of + input have been accumulated, which is what is needed to confirm or deny a + gzip header. Before this, gzdirect() will return true (1). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose(gzFile file); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); +/* + Return the error message for the last error which occurred on file. + If errnum is not NULL, *errnum is set to zlib error number. If an error + occurred in the file system and not in the compression library, *errnum is + set to Z_ERRNO and the application may consult errno to get the exact error + code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr(gzFile file); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); +/* + Same as adler32(), but with a size_t length. Note that a long is 32 bits + on Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); +/* + Same as crc32(), but with a size_t length. Note that a long is 32 bits on + Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. len2 must be non-negative, otherwise zero is returned. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). len2 must be non-negative, otherwise zero is returned. +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zopfli.h b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zopfli.h new file mode 100644 index 0000000..c079662 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/include/zopfli.h @@ -0,0 +1,94 @@ +/* +Copyright 2011 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: lode.vandevenne@gmail.com (Lode Vandevenne) +Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala) +*/ + +#ifndef ZOPFLI_ZOPFLI_H_ +#define ZOPFLI_ZOPFLI_H_ + +#include +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Options used throughout the program. +*/ +typedef struct ZopfliOptions { + /* Whether to print output */ + int verbose; + + /* Whether to print more detailed output */ + int verbose_more; + + /* + Maximum amount of times to rerun forward and backward pass to optimize LZ77 + compression cost. Good values: 10, 15 for small files, 5 for files over + several MB in size or it will be too slow. + */ + int numiterations; + + /* + If true, splits the data in multiple deflate blocks with optimal choice + for the block boundaries. Block splitting gives better compression. Default: + true (1). + */ + int blocksplitting; + + /* + No longer used, left for compatibility. + */ + int blocksplittinglast; + + /* + Maximum amount of blocks to split into (0 for unlimited, but this can give + extreme results that hurt compression on some files). Default value: 15. + */ + int blocksplittingmax; +} ZopfliOptions; + +/* Initializes options with default values. */ +void ZopfliInitOptions(ZopfliOptions* options); + +/* Output format */ +typedef enum { + ZOPFLI_FORMAT_GZIP, + ZOPFLI_FORMAT_ZLIB, + ZOPFLI_FORMAT_DEFLATE +} ZopfliFormat; + +/* +Compresses according to the given output format and appends the result to the +output. + +options: global program options +output_type: the output format to use +out: pointer to the dynamic output array to which the result is appended. Must + be freed after use +outsize: pointer to the dynamic output array size +*/ +void ZopfliCompress(const ZopfliOptions* options, ZopfliFormat output_type, + const unsigned char* in, size_t insize, + unsigned char** out, size_t* outsize); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ZOPFLI_ZOPFLI_H_ */ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libjpeg.a b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libjpeg.a new file mode 100644 index 0000000..95a7934 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libjpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libqpdf.a b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libqpdf.a new file mode 100644 index 0000000..f2f8d81 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libqpdf.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libturbojpeg.a b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libturbojpeg.a new file mode 100644 index 0000000..a18741d Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libturbojpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libz.a b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libz.a new file mode 100644 index 0000000..94b6905 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libz.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libz.so b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libz.so new file mode 100644 index 0000000..f017ba6 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libz.so differ diff --git a/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libzopfli.a b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libzopfli.a new file mode 100644 index 0000000..2fb0266 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/armeabi-v7a/lib/libzopfli.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/jconfig.h b/app/src/main/cpp/third_party/pdf-android/x86/include/jconfig.h new file mode 100644 index 0000000..17f95c8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/jconfig.h @@ -0,0 +1,60 @@ +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ +#define JPEG_LIB_VERSION 80 + +/* libjpeg-turbo version */ +#define LIBJPEG_TURBO_VERSION 3.1.90 + +/* libjpeg-turbo version in integer form */ +#define LIBJPEG_TURBO_VERSION_NUMBER 3001090 + +/* Support arithmetic encoding when using 8-bit samples */ +#define C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding when using 8-bit samples */ +#define D_ARITH_CODING_SUPPORTED 1 + +/* Support in-memory source/destination managers */ +#define MEM_SRCDST_SUPPORTED 1 + +/* Use accelerated SIMD routines when using 8-bit samples */ +/* #undef WITH_SIMD */ + +/* This version of libjpeg-turbo supports run-time selection of data precision, + * so BITS_IN_JSAMPLE is no longer used to specify the data precision at build + * time. However, some downstream software expects the macro to be defined. + * Since 12-bit data precision is an opt-in feature that requires explicitly + * calling 12-bit-specific libjpeg API functions and using 12-bit-specific data + * types, the unmodified portion of the libjpeg API still behaves as if it were + * built for 8-bit precision, and JSAMPLE is still literally an 8-bit data + * type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here. + */ +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif + +#ifdef _WIN32 + +#undef RIGHT_SHIFT_IS_UNSIGNED + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + +/* Define "INT32" as int, not long, per Windows custom */ +#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ +typedef short INT16; +typedef signed int INT32; +#endif +#define XMD_H /* prevent jmorecfg.h from redefining it */ + +#else + +/* Define if your (broken) compiler shifts signed values as if they were + unsigned. */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/jerror.h b/app/src/main/cpp/third_party/pdf-android/x86/include/jerror.h new file mode 100644 index 0000000..892edc3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/jerror.h @@ -0,0 +1,336 @@ +/* + * jerror.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2014, 2017, 2021-2023, 2026, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code, string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code, string) code, + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented") +#endif +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#endif +JMESSAGE(JERR_BAD_DCT_COEF, + "DCT coefficient (lossy) or spatial difference (lossless) out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive/lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Requested features are incompatible") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Memory limit exceeded") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED) +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +#endif +JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_RESTART, + "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT3(cinfo, code, p1, p2, p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXITS(cinfo, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX - 1), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo, lvl, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS1(cinfo, lvl, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS2(cinfo, lvl, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMSS(cinfo, lvl, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/jmorecfg.h b/app/src/main/cpp/third_party/pdf-android/x86/include/jmorecfg.h new file mode 100644 index 0000000..a4df71c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/jmorecfg.h @@ -0,0 +1,389 @@ +/* + * jmorecfg.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, 2026, + * D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255. + * However, darn few applications need more than 4 channels (maybe 5 for CMYK + + * alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +/* JSAMPLE should be the smallest type that will hold the values 0..255. */ + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int)(value)) + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + + +/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */ + +typedef short J12SAMPLE; + +#define MAXJ12SAMPLE 4095 +#define CENTERJ12SAMPLE 2048 + + +/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */ + +typedef unsigned short J16SAMPLE; + +#define MAXJ16SAMPLE 65535 +#define CENTERJ16SAMPLE 32768 + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +typedef unsigned char UINT8; + +/* UINT16 must hold at least the values 0..65535. */ + +typedef unsigned short UINT16; + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. + * + * NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were + * sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to + * long. It also wasn't common (or at least as common) in 1994 for INT32 to be + * defined by platform headers. Since then, however, INT32 is defined in + * several other common places: + * + * Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on + * 32-bit platforms (i.e always a 32-bit signed type.) + * + * basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type + * on modern platforms.) + * + * qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on + * modern platforms.) + * + * This is a recipe for conflict, since "long" and "int" aren't always + * compatible types. Since the definition of INT32 has technically been part + * of the libjpeg API for more than 20 years, we can't remove it, but we do not + * use it internally any longer. We instead define a separate type (JLONG) + * for internal use, which ensures that internal behavior will always be the + * same regardless of any external headers that may be included. + */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. (Note that changing this datatype will + * potentially require modifying the SIMD code. The x86-64 SIMD extensions, + * in particular, assume a 32-bit JDIMENSION.) + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JMETHOD(type, methodname, arglist) type (*methodname) arglist + + +/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS), + * but again, some software relies on this macro. + */ + +#undef FAR +#define FAR + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* accurate integer method */ +#define DCT_IFAST_SUPPORTED /* less accurate int method [legacy feature] */ +#define DCT_FLOAT_SUPPORTED /* floating-point method [legacy feature] */ + +/* Encoder capability options: */ + +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + C_MULTISCAN_FILES_SUPPORTED and + ENTROPY_OPT_SUPPORTED) */ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for lossless JPEG: the default tables don't + * work for lossless mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires + DCT_ISLOW_SUPPORTED) */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial + * feature of libjpeg. The idea was that, if an application developer needed + * to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could + * change these macros, rebuild libjpeg, and link their application statically + * with it. In reality, few people ever did this, because there were some + * severe restrictions involved (cjpeg and djpeg no longer worked properly, + * compressing/decompressing RGB JPEGs no longer worked properly, and the color + * quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since + * all of the O/S-supplied versions of libjpeg were built with the default + * values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications + * have come to regard these values as immutable. + * + * The libjpeg-turbo colorspace extensions provide a much cleaner way of + * compressing from/decompressing to buffers with arbitrary component orders + * and pixel sizes. Thus, we do not support changing the values of RGB_RED, + * RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions + * listed above, changing these values will also break the SIMD extensions and + * the regression tests. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + +#define JPEG_NUMCS 17 + +#define EXT_RGB_RED 0 +#define EXT_RGB_GREEN 1 +#define EXT_RGB_BLUE 2 +#define EXT_RGB_PIXELSIZE 3 + +#define EXT_RGBX_RED 0 +#define EXT_RGBX_GREEN 1 +#define EXT_RGBX_BLUE 2 +#define EXT_RGBX_PIXELSIZE 4 + +#define EXT_BGR_RED 2 +#define EXT_BGR_GREEN 1 +#define EXT_BGR_BLUE 0 +#define EXT_BGR_PIXELSIZE 3 + +#define EXT_BGRX_RED 2 +#define EXT_BGRX_GREEN 1 +#define EXT_BGRX_BLUE 0 +#define EXT_BGRX_PIXELSIZE 4 + +#define EXT_XBGR_RED 3 +#define EXT_XBGR_GREEN 2 +#define EXT_XBGR_BLUE 1 +#define EXT_XBGR_PIXELSIZE 4 + +#define EXT_XRGB_RED 1 +#define EXT_XRGB_GREEN 2 +#define EXT_XRGB_BLUE 3 +#define EXT_XRGB_PIXELSIZE 4 + +static const int rgb_red[JPEG_NUMCS] = { + -1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED, + EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + -1 +}; + +static const int rgb_green[JPEG_NUMCS] = { + -1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN, + EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + -1 +}; + +static const int rgb_blue[JPEG_NUMCS] = { + -1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE, + EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + -1 +}; + +static const int rgb_pixelsize[JPEG_NUMCS] = { + -1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE, + EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + -1 +}; + +/* Definitions for speed-related optimizations. */ + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#ifndef WITH_SIMD +#define MULTIPLIER int /* type for fastest integer multiply */ +#else +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +#endif +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + */ + +#ifndef FAST_FLOAT +#define FAST_FLOAT float +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/jpeglib.h b/app/src/main/cpp/third_party/pdf-android/x86/include/jpeglib.h new file mode 100644 index 0000000..f7076a1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/jpeglib.h @@ -0,0 +1,1223 @@ +/* + * jpeglib.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022-2024, + D. R. Commander. + * Copyright (C) 2015, Google, Inc. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +/* NOTE: This header file does not include stdio.h, despite the fact that it + * uses FILE and size_t. That is by design, since the libjpeg API predates the + * widespread adoption of ANSI/ISO C. Referring to libjpeg.txt, it is a + * documented requirement that calling programs "include system headers that + * define at least the typedefs FILE and size_t" before including jpeglib.h. + * Technically speaking, changing that requirement by including stdio.h here + * would break backward API compatibility. Please do not file bug reports, + * feature requests, or pull requests regarding this. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +/* NOTE: In lossless mode, an MCU contains one or more samples rather than one + * or more 8x8 DCT blocks, so the term "data unit" is used to generically + * describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To + * preserve backward API/ABI compatibility, the field and macro names retain + * the "block" terminology. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + */ + +typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples with + 2-bit through 8-bit data precision. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some JSAMPLE rows (a 2-D JSAMPLE + array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D JSAMPLE array: top index is color */ + +typedef J12SAMPLE *J12SAMPROW; /* ptr to one image row of pixel samples + with 9-bit through 12-bit data + precision. */ +typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some J12SAMPLE rows (a 2-D + J12SAMPLE array) */ +typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D J12SAMPLE array: top index is + color */ + +typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of pixel samples + with 13-bit through 16-bit data + precision. */ +typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some J16SAMPLE rows (a 2-D + J16SAMPLE array) */ +typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D J16SAMPLE array: top index is + color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * In lossy mode, any dummy blocks added to complete an MCU are not counted; + * therefore these values do not depend on whether a scan is interleaved or + * not. In lossless mode, these are always equal to the image width and + * height. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a data unit in samples. Always DCTSIZE for lossy compression. + * For lossy decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values from 1 to 16 are supported. Note that different components may + * receive different IDCT scalings. In lossless mode, this is always equal + * to 1. + */ +#if JPEG_LIB_VERSION >= 70 + int DCT_h_scaled_size; + int DCT_v_scaled_size; +#else + int DCT_scaled_size; +#endif + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For lossy decompression, IDCT scaling is + * included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) + * In lossless mode, these are always equal to the image width and height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ + int last_col_width; /* # of non-dummy data units across in last MCU */ + int last_row_height; /* # of non-dummy data units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL *quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void *dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + (Ss is the predictor selection value in + lossless mode) */ + int Ah, Al; /* progressive JPEG successive approx. parms + (Al is the point transform value in lossless + mode) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct *jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET *data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +#define JCS_EXTENSIONS 1 +#define JCS_ALPHA_EXTENSIONS 1 + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue as specified by the RGB_RED, + RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_EXT_RGB, /* red/green/blue */ + JCS_EXT_RGBX, /* red/green/blue/x */ + JCS_EXT_BGR, /* blue/green/red */ + JCS_EXT_BGRX, /* blue/green/red/x */ + JCS_EXT_XBGR, /* x/blue/green/red */ + JCS_EXT_XRGB, /* x/red/green/blue */ + /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, + or JCS_EXT_XRGB during decompression, the X byte is undefined, and in + order to ensure the best performance, libjpeg-turbo can set that byte to + whatever value it wishes. Use the following colorspace constants to + ensure that the X byte is set to 0xFF, so that it can be interpreted as an + opaque alpha channel. */ + JCS_EXT_RGBA, /* red/green/blue/alpha */ + JCS_EXT_BGRA, /* blue/green/red/alpha */ + JCS_EXT_ABGR, /* alpha/blue/green/red */ + JCS_EXT_ARGB, /* alpha/red/green/blue */ + JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue + [decompression only] */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* accurate integer method */ + JDCT_IFAST, /* less accurate integer method [legacy feature] */ + JDCT_FLOAT /* floating-point method [legacy feature] */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr *err; /* Error handler module */ \ + struct jpeg_memory_mgr *mem; /* Memory manager module */ \ + struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \ + void *client_data; /* Available for use by application */ \ + boolean is_decompressor; /* So common code can tell which is which */ \ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct *j_common_ptr; +typedef struct jpeg_compress_struct *j_compress_ptr; +typedef struct jpeg_decompress_struct *j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr *dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + +#if JPEG_LIB_VERSION >= 70 + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ +#endif + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; +#if JPEG_LIB_VERSION >= 70 + int q_scale_factor[NUM_QUANT_TBLS]; +#endif + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info *scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ +#if JPEG_LIB_VERSION >= 70 + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ +#endif + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or + difference controller */ + /* The coefficient or difference controller receives data in units of MCU + * rows as defined for fully interleaved scans (whether the JPEG file is + * interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE + * sample rows of each component in an "iMCU" (interleaved MCU) row. In + * lossless mode, total_iMCU_rows is always equal to the image height. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ +#endif + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master *master; + struct jpeg_c_main_controller *main; + struct jpeg_c_prep_controller *prep; + struct jpeg_c_coef_controller *coef; + struct jpeg_marker_writer *marker; + struct jpeg_color_converter *cconvert; + struct jpeg_downsampler *downsample; + struct jpeg_forward_dct *fdct; + struct jpeg_entropy_encoder *entropy; + jpeg_scan_info *script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr *src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array + If data_precision is 12, then this is + actually a J12SAMPARRAY, so callers must + type-cast it in order to read/write 12-bit + samples from/to the array. */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + +#if JPEG_LIB_VERSION >= 80 + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ +#endif + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#else + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient or difference controller's input and output progress is + * measured in units of "iMCU" (interleaved MCU) rows. These are the same as + * MCU rows in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor + * DCT block rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. + * In lossless mode, total_iMCU_rows is always equal to the image height. + */ + + JSAMPLE *sample_range_limit; /* table for fast range-limiting + If data_precision is 9 to 12, then this is + actually a J12SAMPLE pointer, and if + data_precision is 13 to 16, then this is + actually a J16SAMPLE pointer, so callers + must type-cast it in order to read samples + from the array. */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ +#endif + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master *master; + struct jpeg_d_main_controller *main; + struct jpeg_d_coef_controller *coef; + struct jpeg_d_post_controller *post; + struct jpeg_input_controller *inputctl; + struct jpeg_marker_reader *marker; + struct jpeg_entropy_decoder *entropy; + struct jpeg_inverse_dct *idct; + struct jpeg_upsampler *upsample; + struct jpeg_color_deconverter *cconvert; + struct jpeg_color_quantizer *cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + void (*error_exit) (j_common_ptr cinfo); + /* Conditionally emit a trace or warning message */ + void (*emit_message) (j_common_ptr cinfo, int msg_level); + /* Routine that actually outputs a trace or error message */ + void (*output_message) (j_common_ptr cinfo); + /* Format a message string for the most recent JPEG error or message */ + void (*format_message) (j_common_ptr cinfo, char *buffer); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + void (*reset_error_mgr) (j_common_ptr cinfo); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const *jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const *addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + void (*progress_monitor) (j_common_ptr cinfo); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + void (*init_destination) (j_compress_ptr cinfo); + boolean (*empty_output_buffer) (j_compress_ptr cinfo); + void (*term_destination) (j_compress_ptr cinfo); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET *next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + void (*init_source) (j_decompress_ptr cinfo); + boolean (*fill_input_buffer) (j_decompress_ptr cinfo); + void (*skip_input_data) (j_decompress_ptr cinfo, long num_bytes); + boolean (*resync_to_restart) (j_decompress_ptr cinfo, int desired); + void (*term_source) (j_decompress_ptr cinfo); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control *jvirt_sarray_ptr; +typedef struct jvirt_barray_control *jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); + void *(*alloc_large) (j_common_ptr cinfo, int pool_id, + size_t sizeofobject); + /* If cinfo->data_precision is 12 or 16, then this method and the + * access_virt_sarray method actually return a J12SAMPARRAY or a + * J16SAMPARRAY, so callers must type-cast the return value in order to + * read/write 12-bit or 16-bit samples from/to the array. + */ + JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows); + JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows); + jvirt_sarray_ptr (*request_virt_sarray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + jvirt_barray_ptr (*request_virt_barray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + void (*realize_virt_arrays) (j_common_ptr cinfo); + JSAMPARRAY (*access_virt_sarray) (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + JBLOCKARRAY (*access_virt_barray) (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + void (*free_pool) (j_common_ptr cinfo, int pool_id); + void (*self_destruct) (j_common_ptr cinfo); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef boolean (*jpeg_marker_parser_method) (j_decompress_ptr cinfo); + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JPP(arglist) arglist + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version, + size_t structsize); +EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, + size_t structsize); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile); +EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, + unsigned long *outsize); +EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, + const unsigned char *inbuffer, unsigned long insize); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo, + J_COLOR_SPACE colorspace); +EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo); +EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality, + boolean force_baseline); +EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor, + boolean force_baseline); +#if JPEG_LIB_VERSION >= 70 +EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo, + boolean force_baseline); +#endif +EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline); +EXTERN(int) jpeg_quality_scaling(int quality); +EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo, + int predictor_selection_value, + int point_transform); +EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo); +EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo, + boolean write_all_tables); +EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); + +#if JPEG_LIB_VERSION >= 70 +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo); +#endif + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_raw_data(j_compress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION num_lines); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker, + unsigned int datalen); +EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo); + +/* Write ICC profile. See libjpeg.txt for usage information. */ +EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len); + + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo); +EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(void) jpeg12_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_raw_data(j_decompress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION max_lines); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number); +EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo); +EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo); +EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +#if JPEG_LIB_VERSION >= 80 +EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo); +#endif +EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo, + int marker_code, + jpeg_marker_parser_method routine); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo); +EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo, + jvirt_barray_ptr *coef_arrays); +EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, + j_compress_ptr dstinfo); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort(j_common_ptr cinfo); +EXTERN(void) jpeg_destroy(j_common_ptr cinfo); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired); + +/* Read ICC profile. See libjpeg.txt for usage information. */ +EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Buffer.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Buffer.hh new file mode 100644 index 0000000..eaa84c9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Buffer.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef BUFFER_HH +#define BUFFER_HH + +#include + +#include +#include +#include +#include + +class Buffer +{ + public: + QPDF_DLL + Buffer(); + + // Create a Buffer object whose memory is owned by the class and will be freed when the Buffer + // object is destroyed. + QPDF_DLL + Buffer(size_t size); + QPDF_DLL + Buffer(std::string&& content); + + // Create a Buffer object whose memory is owned by the caller and will not be freed when the + // Buffer is destroyed. + QPDF_DLL + Buffer(unsigned char* buf, size_t size); + QPDF_DLL + Buffer(std::string& content); + + Buffer(Buffer const&) = delete; + Buffer& operator=(Buffer const&) = delete; + + QPDF_DLL + Buffer(Buffer&&) noexcept; + QPDF_DLL + Buffer& operator=(Buffer&&) noexcept; + QPDF_DLL + ~Buffer(); + QPDF_DLL + size_t getSize() const; + QPDF_DLL + unsigned char const* getBuffer() const; + QPDF_DLL + unsigned char* getBuffer(); + + // Create a new copy of the Buffer. The new Buffer owns an independent copy of the data. + QPDF_DLL + Buffer copy() const; + + // Move the content of the Buffer. After calling this method, the Buffer will be empty if the + // buffer owns its memory. Otherwise, the Buffer will be unchanged. + QPDF_DLL + std::string move(); + + // Return a string_view to the data. + QPDF_DLL + std::string_view view() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char const* data() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char* data(); + + QPDF_DLL + bool empty() const; + + QPDF_DLL + size_t size() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/BufferInputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/BufferInputSource.hh new file mode 100644 index 0000000..0b857b8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/BufferInputSource.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_BUFFERINPUTSOURCE_HH +#define QPDF_BUFFERINPUTSOURCE_HH + +#include +#include + +#include + +class QPDF_DLL_CLASS BufferInputSource: public InputSource +{ + public: + // If own_memory is true, BufferInputSource will delete the buffer when finished with it. + // Otherwise, the caller owns the memory. + QPDF_DLL + BufferInputSource(std::string const& description, Buffer* buf, bool own_memory = false); + + // NB This overload copies the string contents. + QPDF_DLL + BufferInputSource(std::string const& description, std::string const& contents); + QPDF_DLL + ~BufferInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: +#ifndef QPDF_FUTURE + bool own_memory; + std::string description; + Buffer* buf; + qpdf_offset_t cur_offset; + qpdf_offset_t max_offset; +#else + class Members; + + std::unique_ptr m; +#endif +}; + +#endif // QPDF_BUFFERINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/ClosedFileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/ClosedFileInputSource.hh new file mode 100644 index 0000000..56b2cb1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/ClosedFileInputSource.hh @@ -0,0 +1,77 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_CLOSEDFILEINPUTSOURCE_HH +#define QPDF_CLOSEDFILEINPUTSOURCE_HH + +#include + +#include + +class FileInputSource; + +// This is an input source that reads from files, like FileInputSource, except that it opens and +// closes the file surrounding every operation. This decreases efficiency, but it allows many more +// of these to exist at once than the maximum number of open file descriptors. This is used for +// merging large numbers of files. +class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource +{ + public: + QPDF_DLL + ClosedFileInputSource(char const* filename); + + ClosedFileInputSource(ClosedFileInputSource const&) = delete; + ClosedFileInputSource& operator=(ClosedFileInputSource const&) = delete; + + QPDF_DLL + ~ClosedFileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + // The file stays open between calls to stayOpen(true) and stayOpen(false). You can use this to + // surround multiple operations on a single ClosedFileInputSource to reduce the overhead of a + // separate open/close on each call. + QPDF_DLL + void stayOpen(bool); + + private: + QPDF_DLL_PRIVATE + void before(); + QPDF_DLL_PRIVATE + void after(); + + std::string filename; + qpdf_offset_t offset{0}; + std::shared_ptr fis; + bool stay_open{false}; +}; + +#endif // QPDF_CLOSEDFILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Constants.h b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Constants.h new file mode 100644 index 0000000..4b32713 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Constants.h @@ -0,0 +1,297 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFCONSTANTS_H +#define QPDFCONSTANTS_H + +/* + * REMEMBER: + * + * Keep this file 'C' compatible so it can be used from the C and C++ + * interfaces. + */ + +/* ****************************** NOTE ****************************** + +Tl;Dr: new values must be added to the end such that no constant's +numerical value changes, even across major releases. + +Details: + +As new values are added to existing enumerated types in this file, +it is important not to change the actual values of any constants. +This means that, in the absence of explicit assignment of values, +the order of entries can't change even across major releases. Why? +Here are the reasons: + +* Many of these constants are used by the C API. The C API is used + through foreign function call interfaces by users of other languages + who may not have access to or the ability to parse a C header file. + As such, users are likely to hard-code numerical values or create + their own constants whose values match. If we change values here, + their code would break, and there would be no way to detect it short + of noticing a bug. Furthermore, it would be difficult to write code + that properly handled more than one version of the qpdf shared + object (e.g. DLL) since the information about what version of qpdf + is involved is only available at runtime. + +- It has happened from time to time that a user builds an application + with an incorrectly installed qpdf, such as having mismatched header + files and library files. In the event that they are only using qpdf + interfaces that have been stable across the versions in question, + this turns out to be harmless. If they happen to use non-compatible + interfaces, this results usually in a failure to load or an obvious + runtime error. If we change values of constants, it is possible that + code that links and runs may have mismatched values for constants. + This would create a bug that would be extremely difficult to track + down and impossible for qpdf maintainers to reproduce. + +*/ + +/* Exit Codes from QPDFJob and the qpdf CLI */ + +enum qpdf_exit_code_e { + qpdf_exit_success = 0, + /* Normal exit codes */ + qpdf_exit_error = 2, + qpdf_exit_warning = 3, + /* For --is-encrypted and --requires-password */ + qpdf_exit_is_not_encrypted = 2, + qpdf_exit_correct_password = 3, +}; + +/* Error Codes */ + +enum qpdf_error_code_e { + qpdf_e_success = 0, + qpdf_e_internal, /* logic/programming error -- indicates bug */ + qpdf_e_system, /* I/O error, memory error, etc. */ + qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */ + qpdf_e_password, /* incorrect password for encrypted file */ + qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */ + qpdf_e_pages, /* erroneous or unsupported pages structure */ + qpdf_e_object, /* type/bounds errors accessing objects */ + qpdf_e_json, /* error in qpdf JSON */ + qpdf_e_linearization, /* linearization warning */ +}; + +/* Object Types */ + +/* PDF objects represented by QPDFObjectHandle or, in the C API, by + * qpdf_oh, have a unique type code that has one of the values in the + * list below. As new object types are added to qpdf, additional items + * may be added to the list, so code that switches on these values + * should take that into consideration. (Maintainer note: it would be + * better to call this qpdf_ot_* rather than ot_* to reduce likelihood + * of name collision, but changing the names of the values breaks + * backward compatibility.) + */ +enum qpdf_object_type_e { + /* Object types internal to qpdf */ + ot_uninitialized, + ot_reserved, + /* Object types that can occur in the main document */ + ot_null, + ot_boolean, + ot_integer, + ot_real, + ot_string, + ot_name, + ot_array, + ot_dictionary, + ot_stream, + /* Additional object types that can occur in content streams */ + ot_operator, + ot_inlineimage, + /* Object types internal to qpdf */ + ot_unresolved, + ot_destroyed, + ot_reference, +}; + +/* Write Parameters. See QPDFWriter.hh for details. */ + +enum qpdf_object_stream_e { + qpdf_o_disable = 0, /* disable object streams */ + qpdf_o_preserve, /* preserve object streams */ + qpdf_o_generate /* generate object streams */ +}; +enum qpdf_stream_data_e { + qpdf_s_uncompress = 0, /* uncompress stream data */ + qpdf_s_preserve, /* preserve stream data compression */ + qpdf_s_compress /* compress stream data */ +}; + +/* Stream data flags */ + +/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */ +enum qpdf_stream_encode_flags_e { + qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */ + qpdf_ef_normalize = 1 << 1, /* normalize content stream */ +}; +enum qpdf_stream_decode_level_e { + /* These must be in order from less to more decoding. */ + qpdf_dl_none = 0, /* preserve all stream filters */ + qpdf_dl_generalized, /* decode general-purpose filters */ + qpdf_dl_specialized, /* also decode other non-lossy filters */ + qpdf_dl_all /* also decode lossy filters */ +}; +/* For JSON encoding */ +enum qpdf_json_stream_data_e { + qpdf_sj_none = 0, + qpdf_sj_inline, + qpdf_sj_file, +}; + +/* R3 Encryption Parameters */ + +enum qpdf_r3_print_e { + qpdf_r3p_full = 0, /* allow all printing */ + qpdf_r3p_low, /* allow only low-resolution printing */ + qpdf_r3p_none /* allow no printing */ +}; + +/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It + * corresponds to options in Acrobat 5's menus. The new interface in + * QPDFWriter offers more granularity and no longer uses this type. + */ +enum qpdf_r3_modify_e /* Allowed changes: */ +{ + qpdf_r3m_all = 0, /* All editing */ + qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */ + qpdf_r3m_form, /* Fill forms, signing, assembly */ + qpdf_r3m_assembly, /* Only document assembly */ + qpdf_r3m_none /* No modifications */ +}; + +/* Form field flags from the PDF spec */ + +enum pdf_form_field_flag_e { + /* flags that apply to all form fields */ + ff_all_read_only = 1 << 0, + ff_all_required = 1 << 1, + ff_all_no_export = 1 << 2, + + /* flags that apply to fields of type /Btn (button) */ + ff_btn_no_toggle_off = 1 << 14, + ff_btn_radio = 1 << 15, + ff_btn_pushbutton = 1 << 16, + ff_btn_radios_in_unison = 1 << 17, + + /* flags that apply to fields of type /Tx (text) */ + ff_tx_multiline = 1 << 12, + ff_tx_password = 1 << 13, + ff_tx_file_select = 1 << 20, + ff_tx_do_not_spell_check = 1 << 22, + ff_tx_do_not_scroll = 1 << 23, + ff_tx_comb = 1 << 24, + ff_tx_rich_text = 1 << 25, + + /* flags that apply to fields of type /Ch (choice) */ + ff_ch_combo = 1 << 17, + ff_ch_edit = 1 << 18, + ff_ch_sort = 1 << 19, + ff_ch_multi_select = 1 << 21, + ff_ch_do_not_spell_check = 1 << 22, + ff_ch_commit_on_sel_change = 1 << 26 +}; + +/* Annotation flags from the PDF spec */ + +enum pdf_annotation_flag_e { + an_invisible = 1 << 0, + an_hidden = 1 << 1, + an_print = 1 << 2, + an_no_zoom = 1 << 3, + an_no_rotate = 1 << 4, + an_no_view = 1 << 5, + an_read_only = 1 << 6, + an_locked = 1 << 7, + an_toggle_no_view = 1 << 8, + an_locked_contents = 1 << 9 +}; + +/* Encryption/password status for QPDFJob */ +enum qpdf_encryption_status_e { qpdf_es_encrypted = 1 << 0, qpdf_es_password_incorrect = 1 << 1 }; + +/* Page label types */ +enum qpdf_page_label_e { + pl_none, + pl_digits, + pl_alpha_lower, + pl_alpha_upper, + pl_roman_lower, + pl_roman_upper, +}; + +/** + * @enum qpdf_result_e + * @brief Enum representing result codes for qpdf C-API functions. + * + * Results <= qpdf_r_no_warn indicate success without warnings, + * qpdf_r_no_warn < result <= qpdf_r_success indicates success with warnings, and + * qpdf_r_success < result indicates failure. + */ +enum qpdf_result_e { + /* success */ + qpdf_r_ok = 0, + qpdf_r_no_warn = 0xff, /// any result <= qpdf_no_warn indicates success without warning + qpdf_r_success = 0xffff, /// any result <= qpdf_r_success indicates success + /* failure */ + qpdf_r_bad_parameter = 0x10000, + + qpdf_r_no_warn_mask = 0x7fffff00, + qpdf_r_success_mask = 0x7fff0000, +}; + +/** + * @enum qpdf_param_e + * @brief This enumeration defines various parameters and configuration options for qpdf C-API + * functions. + * + * The enum values are grouped into sections based on their functionality, such as global + * options or global limits. For the meaning of individual parameters see `qpdf/global.cc` + */ +enum qpdf_param_e { + /* global state */ + qpdf_p_limit_errors = 0x10020, + + /* global options */ + qpdf_p_inspection_mode = 0x11000, + qpdf_p_default_limits = 0x11100, + /* global limits */ + + /* parser limits */ + qpdf_p_parser_max_nesting = 0x13000, + qpdf_p_parser_max_errors, + qpdf_p_parser_max_container_size, + qpdf_p_parser_max_container_size_damaged, + + /* stream and filter limits */ + qpdf_p_max_stream_filters = 0x14000, + + /* next section = 0x20000 */ + qpdf_enum_max = 0x7fffffff, +}; + +#endif /* QPDFCONSTANTS_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/DLL.h b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/DLL.h new file mode 100644 index 0000000..cc6dcbb --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/DLL.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDF_DLL_HH +#define QPDF_DLL_HH + +/* The first version of qpdf to include the version constants is 10.6.0. */ +#define QPDF_MAJOR_VERSION 12 +#define QPDF_MINOR_VERSION 3 +#define QPDF_PATCH_VERSION 2 + +#ifdef QPDF_FUTURE +# define QPDF_VERSION "12.3.2+future" +#else +# define QPDF_VERSION "12.3.2" +#endif + +/* + * This file defines symbols that control the which functions, + * classes, and methods are exposed to the public ABI (application + * binary interface). See below for a detailed explanation. + */ + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef libqpdf_EXPORTS +# define QPDF_DLL __declspec(dllexport) +# else +# define QPDF_DLL +# endif +# define QPDF_DLL_PRIVATE +#elif defined __GNUC__ +# define QPDF_DLL __attribute__((visibility("default"))) +# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden"))) +#else +# define QPDF_DLL +# define QPDF_DLL_PRIVATE +#endif +#ifdef __GNUC__ +# define QPDF_DLL_CLASS QPDF_DLL +#else +# define QPDF_DLL_CLASS +#endif + +/* + +Here's what's happening. See also https://gcc.gnu.org/wiki/Visibility +for a more in-depth discussion. + +* Everything in the public ABI must be exported. Things not in the + public ABI should not be exported. + +* A class's runtime type information is need if the class is going to + be used as an exception, inherited from, or tested with + dynamic_class. To do these things across a shared object boundary, + runtime type information must be exported. + +* On Windows: + + * For a symbol (function, method, etc.) to be exported into the + public ABI, it must be explicitly marked for export. + + * If you mark a class for export, all symbols in the class, + including private methods, are exported into the DLL, and there is + no way to exclude something from export. + + * A class's run-time type information is made available based on the + presence of a compiler flag (with MSVC), which is always on for + qpdf builds. + + * Marking classes for export should be done only when *building* the + DLL, not when *using* the DLL. + + * It is possible to mark symbols for import for DLL users, but it is + not necessary, and doing it right is complex in our case of being + multi-platform and building both static and shared libraries that + use the same headers, so we don't bother. + + * If we don't export base classes with mingw, the vtables don't end + up in the DLL. + +* On Linux (and other similar systems): + + * Common compilers such as gcc and clang export all symbols into the + public ABI by default. The qpdf build overrides this by using + "visibility=hidden", which makes it behave more like Windows in + that things have to be explicitly exported to appear in the public + ABI. + + * As with Windows, marking a class for export causes everything in + the class, including private methods, the be exported. However, + unlike in Windows: + + * It is possible to explicitly mark symbols as private + + * The only way to get the runtime type and vtable information into + the ABI is to mark the class as exported. + + * It is harmless and sometimes necessary to include the visibility + marks when using the library as well as when building it. In + particular, clang on MacOS requires the visibility marks to + match in both cases. + +What does this mean: + +* On Windows, we never have to export a class, and while there is no + way to "unexport" something, we also have no need to do it. + +* On non-Windows, we have to export some classes, and when we do, we + have to "unexport" some of their parts. + +* We only use the libqpdf_EXPORTS as a conditional for defining the + symbols for Windows builds. + +To achieve this, we use QPDF_DLL_CLASS to export classes, QPDF_DLL to +export methods, and QPDF_DLL_PRIVATE to unexport private methods in +exported classes. + +*/ + +#endif /* QPDF_DLL_HH */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/FileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/FileInputSource.hh new file mode 100644 index 0000000..af42400 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/FileInputSource.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_FILEINPUTSOURCE_HH +#define QPDF_FILEINPUTSOURCE_HH + +#include + +class QPDF_DLL_CLASS FileInputSource: public InputSource +{ + public: + FileInputSource() = default; + QPDF_DLL + FileInputSource(char const* filename); + QPDF_DLL + FileInputSource(char const* description, FILE* filep, bool close_file); + QPDF_DLL + void setFilename(char const* filename); + QPDF_DLL + void setFile(char const* description, FILE* filep, bool close_file); + + FileInputSource(FileInputSource const&) = delete; + FileInputSource& operator=(FileInputSource const&) = delete; + + QPDF_DLL + ~FileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: + bool close_file{false}; + std::string filename; + FILE* file{nullptr}; +}; + +#endif // QPDF_FILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/InputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/InputSource.hh new file mode 100644 index 0000000..bac54ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/InputSource.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_INPUTSOURCE_HH +#define QPDF_INPUTSOURCE_HH + +#include +#include + +#include +#include +#include + +// Remember to use QPDF_DLL_CLASS on anything derived from InputSource so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS InputSource +{ + public: + InputSource() = default; + + virtual ~InputSource() = default; + + class QPDF_DLL_CLASS Finder + { + public: + QPDF_DLL + Finder() = default; + QPDF_DLL + virtual ~Finder() = default; + virtual bool check() = 0; + }; + + QPDF_DLL + void setLastOffset(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getLastOffset() const; + QPDF_DLL + std::string readLine(size_t max_line_length); + + // Find first or last occurrence of a sequence of characters starting within the range defined + // by offset and len such that, when the input source is positioned at the beginning of that + // sequence, finder.check() returns true. If len is 0, the search proceeds until EOF. If a + // qualifying pattern is found, these methods return true and leave the input source positioned + // wherever check() left it at the end of the matching pattern. + QPDF_DLL + bool findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + QPDF_DLL + bool findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + + virtual qpdf_offset_t findAndSkipNextEOL() = 0; + virtual std::string const& getName() const = 0; + virtual qpdf_offset_t tell() = 0; + virtual void seek(qpdf_offset_t offset, int whence) = 0; + virtual void rewind() = 0; + virtual size_t read(char* buffer, size_t length) = 0; + + // Note: you can only unread the character you just read. The specific character is ignored by + // some implementations, and the implementation doesn't check this. Use of unreadCh is + // semantically equivalent to seek(-1, SEEK_CUR) but is much more efficient. + virtual void unreadCh(char ch) = 0; + + // The following methods are for internal use by qpdf only. + inline size_t read(std::string& str, size_t count, qpdf_offset_t at = -1); + inline std::string read(size_t count, qpdf_offset_t at = -1); + size_t read_line(std::string& str, size_t count, qpdf_offset_t at = -1); + std::string read_line(size_t count, qpdf_offset_t at = -1); + inline qpdf_offset_t fastTell(); + inline bool fastRead(char&); + inline void fastUnread(bool); + inline void loadBuffer(); + + protected: + qpdf_offset_t last_offset{0}; + + private: + // State for fast... methods + static const qpdf_offset_t buf_size = 128; + char buffer[buf_size]; + qpdf_offset_t buf_len = 0; + qpdf_offset_t buf_idx = 0; + qpdf_offset_t buf_start = 0; +}; + +#endif // QPDF_INPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/JSON.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/JSON.hh new file mode 100644 index 0000000..3713e73 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/JSON.hh @@ -0,0 +1,404 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef JSON_HH +#define JSON_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Pipeline; +class InputSource; + +// This is a simple JSON serializer and parser, primarily designed for serializing QPDF Objects as +// JSON. While it may work as a general-purpose JSON parser/serializer, there are better options. +// JSON objects contain their data as smart pointers. When one JSON object is added to another, this +// pointer is copied. This means you can create temporary JSON objects on the stack, add them to +// other objects, and let them go out of scope safely. It also means that if a JSON object is added +// in more than one place, all copies share the underlying data. This makes them similar in +// structure and behavior to QPDFObjectHandle and may feel natural within the QPDF codebase, but it +// is also a good reason not to use this as a general-purpose JSON package. +class JSON +{ + public: + static int constexpr LATEST = 2; + + JSON() = default; + + QPDF_DLL + std::string unparse() const; + + // Write the JSON object through a pipeline. The `depth` parameter specifies how deeply nested + // this is in another JSON structure, which makes it possible to write clean-looking JSON + // incrementally. + QPDF_DLL + void write(Pipeline*, size_t depth = 0) const; + + // Helper methods for writing JSON incrementally. + // + // "first" -- Several methods take a `bool& first` parameter. The open methods always set it to + // true, and the methods to output items always set it to false. This way, the item and close + // methods can always know whether or not a first item is being written. The intended mode of + // operation is to start with a new `bool first = true` each time a new container is opened and + // to pass that `first` through to all the methods that are called to add top-level items to the + // container as well as to close the container. This lets the JSON object use it to keep track + // of when it's writing a first object and when it's not. If incrementally writing multiple + // levels of depth, a new `first` should be used for each new container that is opened. + // + // "depth" -- Indicate the level of depth. This is used for consistent indentation. When writing + // incrementally, whenever you call a method to add an item to a container, the value of `depth` + // should be one more than whatever value is passed to the container open and close methods. + + // Open methods ignore the value of first and set it to false + QPDF_DLL + static void writeDictionaryOpen(Pipeline*, bool& first, size_t depth = 0); + QPDF_DLL + static void writeArrayOpen(Pipeline*, bool& first, size_t depth = 0); + // Close methods don't modify first. A true value indicates that we are closing an empty object. + QPDF_DLL + static void writeDictionaryClose(Pipeline*, bool first, size_t depth = 0); + QPDF_DLL + static void writeArrayClose(Pipeline*, bool first, size_t depth = 0); + // The item methods use the value of first to determine if this is the first item and always set + // it to false. + QPDF_DLL + static void writeDictionaryItem( + Pipeline*, bool& first, std::string const& key, JSON const& value, size_t depth = 0); + // Write just the key of a new dictionary item, useful if writing nested structures. Calls + // writeNext. + QPDF_DLL + static void + writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth = 0); + QPDF_DLL + static void writeArrayItem(Pipeline*, bool& first, JSON const& element, size_t depth = 0); + // If writing nested structures incrementally, call writeNext before opening a new array or + // container in the midst of an existing one. The `first` you pass to writeNext should be the + // one for the parent object. The depth should be the one for the child object. Then start a new + // `first` for the nested item. Note that writeDictionaryKey and writeArrayItem call writeNext + // for you, so this is most important when writing subsequent items or container openers to an + // array. + QPDF_DLL + static void writeNext(Pipeline* p, bool& first, size_t depth = 0); + + // The JSON spec calls dictionaries "objects", but that creates too much confusion when + // referring to instances of the JSON class. + QPDF_DLL + static JSON makeDictionary(); + // addDictionaryMember returns the newly added item. + QPDF_DLL + JSON addDictionaryMember(std::string const& key, JSON const&); + QPDF_DLL + static JSON makeArray(); + // addArrayElement returns the newly added item. + QPDF_DLL + JSON addArrayElement(JSON const&); + QPDF_DLL + static JSON makeString(std::string const& utf8); + QPDF_DLL + static JSON makeInt(long long int value); + QPDF_DLL + static JSON makeReal(double value); + QPDF_DLL + static JSON makeNumber(std::string const& encoded); + QPDF_DLL + static JSON makeBool(bool value); + QPDF_DLL + static JSON makeNull(); + + // A blob serializes as a string. The function will be called by JSON with a pipeline and should + // write binary data to the pipeline but not call finish(). JSON will call finish() at the right + // time. + QPDF_DLL + static JSON makeBlob(std::function); + + QPDF_DLL + bool isArray() const; + + QPDF_DLL + bool isDictionary() const; + + // Accessors. Accessor behavior: + // + // - If argument is wrong type, including null, return false + // - If argument is right type, return true and initialize the value + + QPDF_DLL + bool getString(std::string& utf8) const; + QPDF_DLL + bool getNumber(std::string& value) const; + QPDF_DLL + bool getBool(bool& value) const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + JSON getDictItem(std::string const& key) const; + QPDF_DLL + bool forEachDictItem(std::function fn) const; + QPDF_DLL + bool forEachArrayItem(std::function fn) const; + + // Check this JSON object against a "schema". This is not a schema according to any standard. + // It's just a template of what the JSON is supposed to contain. The checking does the + // following: + // + // * The schema is a nested structure containing dictionaries, single-element arrays, and + // strings only. + // * Recursively walk the schema. In the items below, "schema object" refers to an object in + // the schema, and "checked object" refers to the corresponding part of the object being + // checked. + // * If the schema object is a dictionary, the checked object must have a dictionary in the + // same place with the same keys. If flags contains f_optional, a key in the schema does not + // have to be present in the object. Otherwise, all keys have to be present. Any key in the + // object must be present in the schema. + // * If the schema object is an array of length 1, the checked object may either be a single + // item or an array of items. The single item or each element of the checked object's + // array is validated against the single element of the schema's array. The rationale behind + // this logic is that a single element may appear wherever the schema allows a + // variable-length array. This makes it possible to start allowing an array in the future + // where a single element was previously required without breaking backward compatibility. + // * If the schema object is an array of length > 1, the checked object must be an array of + // the same length. In this case, each element of the checked object array is validated + // against the corresponding element of the schema array. + // * Otherwise, the value must be a string whose value is a description of the object's + // corresponding value, which may have any type. + // + // QPDF's JSON output conforms to certain strict compatibility rules as discussed in the manual. + // The idea is that a JSON structure created manually in qpdf.cc doubles as both JSON help + // information and a schema for validating the JSON that qpdf generates. Any discrepancies are a + // bug in qpdf. + // + // Flags is a bitwise or of values from check_flags_e. + enum check_flags_e { + f_none = 0, + f_optional = 1 << 0, + }; + QPDF_DLL + bool checkSchema(JSON schema, unsigned long flags, std::list& errors); + + // Same as passing 0 for flags + QPDF_DLL + bool checkSchema(JSON schema, std::list& errors); + + // A pointer to a Reactor class can be passed to parse, which will enable the caller to react + // to incremental events in the construction of the JSON object. This makes it possible to + // implement SAX-like handling of very large JSON objects. + class QPDF_DLL_CLASS Reactor + { + public: + virtual ~Reactor() = default; + + // The start/end methods are called when parsing of a dictionary or array is started or + // ended. The item methods are called when an item is added to a dictionary or array. When + // adding a container to another container, the item method is called with an empty + // container before the lower container's start method is called. See important notes in + // "Item methods" below. + + // During parsing of a JSON string, the parser is operating on a single object at a time. + // When a dictionary or array is started, a new context begins, and when that dictionary or + // array is ended, the previous context is resumed. So, for + // example, if you have `{"a": [1]}`, you will receive the + // following method calls + // + // dictionaryStart -- current object is the top-level dictionary + // dictionaryItem -- called with "a" and an empty array + // arrayStart -- current object is the array + // arrayItem -- called with the "1" object + // containerEnd -- now current object is the dictionary again + // containerEnd -- current object is undefined + // + // If the top-level item in a JSON string is a scalar, the topLevelScalar() method will be + // called. No argument is passed since the object is the same as what is returned by + // parse(). + + QPDF_DLL + virtual void dictionaryStart() = 0; + QPDF_DLL + virtual void arrayStart() = 0; + QPDF_DLL + virtual void containerEnd(JSON const& value) = 0; + QPDF_DLL + virtual void topLevelScalar() = 0; + + // Item methods: + // + // The return value of the item methods indicate whether the item has been "consumed". If + // the item method returns true, then the item will not be added to the containing JSON + // object. This is what allows arbitrarily large JSON objects + // to be parsed and not have to be kept in memory. + // + // NOTE: When a dictionary or an array is added to a container, the dictionaryItem or + // arrayItem method is called when the child item's start delimiter is encountered, so the + // JSON object passed in at that time will always be in its initial, empty state. + // Additionally, the child item's start method is not called until after the parent item's + // item method is called. This makes it possible to keep track of the current depth level by + // incrementing level on start methods and decrementing on end methods. + + QPDF_DLL + virtual bool dictionaryItem(std::string const& key, JSON const& value) = 0; + QPDF_DLL + virtual bool arrayItem(JSON const& value) = 0; + }; + + // Create a JSON object from a string. + QPDF_DLL + static JSON parse(std::string const&); + // Create a JSON object from an input source. See above for information about how to use the + // Reactor. + QPDF_DLL + static JSON parse(InputSource&, Reactor* reactor = nullptr); + + // parse calls setOffsets to set the inclusive start and non-inclusive end offsets of an object + // relative to its input string. Otherwise, both values are 0. + QPDF_DLL + void setStart(qpdf_offset_t); + QPDF_DLL + void setEnd(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getStart() const; + QPDF_DLL + qpdf_offset_t getEnd() const; + + // The following class does not form part of the public API and is for internal use only. + + class Writer; + + private: + static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter); + + enum value_type_e { + vt_none, + vt_dictionary, + vt_array, + vt_string, + vt_number, + vt_bool, + vt_null, + vt_blob, + }; + + struct JSON_value + { + JSON_value(value_type_e type_code) : + type_code(type_code) + { + } + virtual ~JSON_value() = default; + virtual void write(Pipeline*, size_t depth) const = 0; + const value_type_e type_code{vt_none}; + }; + struct JSON_dictionary: public JSON_value + { + JSON_dictionary() : + JSON_value(vt_dictionary) + { + } + ~JSON_dictionary() override = default; + void write(Pipeline*, size_t depth) const override; + std::map members; + }; + struct JSON_array; + struct JSON_string: public JSON_value + { + JSON_string(std::string const& utf8); + ~JSON_string() override = default; + void write(Pipeline*, size_t depth) const override; + std::string utf8; + }; + struct JSON_number: public JSON_value + { + JSON_number(long long val); + JSON_number(double val); + JSON_number(std::string const& val); + ~JSON_number() override = default; + void write(Pipeline*, size_t depth) const override; + std::string encoded; + }; + struct JSON_bool: public JSON_value + { + JSON_bool(bool val); + ~JSON_bool() override = default; + void write(Pipeline*, size_t depth) const override; + bool value; + }; + struct JSON_null: public JSON_value + { + JSON_null() : + JSON_value(vt_null) + { + } + ~JSON_null() override = default; + void write(Pipeline*, size_t depth) const override; + }; + struct JSON_blob: public JSON_value + { + JSON_blob(std::function fn); + ~JSON_blob() override = default; + void write(Pipeline*, size_t depth) const override; + std::function fn; + }; + + JSON(std::unique_ptr); + + static void checkSchemaInternal( + JSON_value* this_v, + JSON_value* sch_v, + unsigned long flags, + std::list& errors, + std::string prefix); + + class Members + { + friend class JSON; + + public: + ~Members() = default; + + private: + Members(std::unique_ptr); + Members(Members const&) = delete; + + std::unique_ptr value; + // start and end are only populated for objects created by parse + qpdf_offset_t start{0}; + qpdf_offset_t end{0}; + }; + + std::shared_ptr m; +}; + +struct JSON::JSON_array: public JSON_value +{ + JSON_array() : + JSON_value(vt_array) + { + } + ~JSON_array() override = default; + void write(Pipeline*, size_t depth) const override; + std::vector elements; +}; + +#endif // JSON_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/ObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/ObjectHandle.hh new file mode 100644 index 0000000..9cf4dc6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/ObjectHandle.hh @@ -0,0 +1,155 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef OBJECTHANDLE_HH +#define OBJECTHANDLE_HH + +#include +#include +#include + +#include +#include +#include + +#include +#include + +class QPDF; +class QPDF_Dictionary; +class QPDFObject; +class QPDFObjectHandle; + +namespace qpdf +{ + class Array; + class BaseDictionary; + class Dictionary; + class Integer; + class Stream; + + enum typed : std::uint8_t { strict = 0, any_flag = 1, optional = 2, any = 3, error = 4 }; + + // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only + // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, + // QPDFObjGen and bool. + class BaseHandle + { + friend class ::QPDF; + + public: + explicit inline operator bool() const; + inline operator QPDFObjectHandle() const; + QPDF_DLL + operator QPDFObjGen() const; + + // The rest of the header file is for qpdf internal use only. + + // Return true if both object handles refer to the same underlying object. + bool + operator==(BaseHandle const& other) const + { + return obj == other.obj; + } + + // For arrays, return the number of items in the array. + // For null-like objects, return 0. + // For all other objects, return 1. + size_t size() const; + + // Return 'true' if size() == 0. + bool + empty() const + { + return size() == 0; + } + + QPDFObjectHandle operator[](size_t n) const; + QPDFObjectHandle operator[](int n) const; + + QPDFObjectHandle& at(std::string const& key) const; + bool contains(std::string const& key) const; + size_t erase(std::string const& key); + QPDFObjectHandle& find(std::string const& key) const; + bool replace(std::string const& key, QPDFObjectHandle value); + QPDFObjectHandle const& operator[](std::string const& key) const; + + std::shared_ptr copy(bool shallow = false) const; + // Recursively remove association with any QPDF object. This method may only be called + // during final destruction. + void disconnect(bool only_direct = true); + inline QPDFObjGen id_gen() const; + inline bool indirect() const; + inline bool null() const; + inline qpdf_offset_t offset() const; + inline QPDF* qpdf() const; + inline qpdf_object_type_e raw_type_code() const; + inline qpdf_object_type_e resolved_type_code() const; + inline qpdf_object_type_e type_code() const; + std::string unparse() const; + void write_json(int json_version, JSON::Writer& p) const; + static void warn(QPDF*, QPDFExc&&); + void warn(QPDFExc&&) const; + void warn(std::string const& warning) const; + + inline std::shared_ptr const& obj_sp() const; + inline QPDFObjectHandle oh() const; + + protected: + BaseHandle() = default; + BaseHandle(std::shared_ptr const& obj) : + obj(obj) {}; + BaseHandle(std::shared_ptr&& obj) : + obj(std::move(obj)) {}; + BaseHandle(BaseHandle const&) = default; + BaseHandle& operator=(BaseHandle const&) = default; + BaseHandle(BaseHandle&&) = default; + BaseHandle& operator=(BaseHandle&&) = default; + + inline BaseHandle(QPDFObjectHandle const& oh); + inline BaseHandle(QPDFObjectHandle&& oh); + + ~BaseHandle() = default; + + template + T* as() const; + + inline void assign(qpdf_object_type_e required, BaseHandle const& other); + inline void assign(qpdf_object_type_e required, BaseHandle&& other); + + inline void nullify(); + + std::string description() const; + + inline QPDFObjectHandle const& get(std::string const& key) const; + + void no_ci_warn_if(bool condition, std::string const& warning) const; + void no_ci_stop_if(bool condition, std::string const& warning) const; + void no_ci_stop_damaged_if(bool condition, std::string const& warning) const; + std::invalid_argument invalid_error(std::string const& method) const; + std::runtime_error type_error(char const* expected_type) const; + QPDFExc type_error(char const* expected_type, std::string const& message) const; + char const* type_name() const; + + std::shared_ptr obj; + }; + +} // namespace qpdf + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/PDFVersion.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/PDFVersion.hh new file mode 100644 index 0000000..32b1df5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/PDFVersion.hh @@ -0,0 +1,65 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PDFVERSION_HH +#define PDFVERSION_HH + +#include +#include + +// Represent a PDF version. PDF versions are typically major.minor, but PDF 1.7 has several +// extension levels as the ISO 32000 spec was in progress. This class helps with comparison of +// versions. +class PDFVersion +{ + public: + PDFVersion() = default; + PDFVersion(PDFVersion const&) = default; + PDFVersion& operator=(PDFVersion const&) = default; + + QPDF_DLL + PDFVersion(int major, int minor, int extension = 0); + QPDF_DLL + bool operator<(PDFVersion const& rhs) const; + QPDF_DLL + bool operator==(PDFVersion const& rhs) const; + + // Replace this version with the other one if the other one is greater. + QPDF_DLL + void updateIfGreater(PDFVersion const& other); + + // Initialize a string and integer suitable for passing to QPDFWriter::setMinimumPDFVersion or + // QPDFWriter::forcePDFVersion. + QPDF_DLL + void getVersion(std::string& version, int& extension_level) const; + + QPDF_DLL + int getMajor() const; + QPDF_DLL + int getMinor() const; + QPDF_DLL + int getExtensionLevel() const; + + private: + int major_version{0}; + int minor_version{0}; + int extension_level{0}; +}; + +#endif // PDFVERSION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pipeline.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pipeline.hh new file mode 100644 index 0000000..6e07c4f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pipeline.hh @@ -0,0 +1,115 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PIPELINE_HH +#define PIPELINE_HH + +#include + +#include +#include + +// Generalized Pipeline interface. By convention, subclasses of Pipeline are called Pl_Something. +// +// When an instance of Pipeline is created with a pointer to a next pipeline, that pipeline writes +// its data to the next one when it finishes with it. In order to make possible a usage style in +// which a pipeline may be passed to a function which may stick other pipelines in front of it, the +// allocator of a pipeline is responsible for its destruction. In other words, one pipeline object +// does not attempt to manage the memory of its successor. +// +// The client is required to call finish() before destroying a Pipeline in order to avoid loss of +// data. A Pipeline class should not throw an exception in the destructor if this hasn't been done +// though since doing so causes too much trouble when deleting pipelines during error conditions. +// +// Some pipelines are reusable (i.e., you can call write() after calling finish() and can call +// finish() multiple times) while others are not. It is up to the caller to use a pipeline +// according to its own restrictions. +// +// Remember to use QPDF_DLL_CLASS on anything derived from Pipeline so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS Pipeline +{ + public: + QPDF_DLL + Pipeline(char const* identifier, Pipeline* next); + + virtual ~Pipeline() = default; + + // Subclasses should implement write and finish to do their jobs and then, if they are not + // end-of-line pipelines, call getNext()->write or getNext()->finish. + QPDF_DLL + virtual void write(unsigned char const* data, size_t len) = 0; + QPDF_DLL + virtual void finish() = 0; + QPDF_DLL + std::string getIdentifier() const; + + // These are convenience methods for making it easier to write certain other types of data to + // pipelines without having to cast. The methods that take char const* expect null-terminated C + // strings and do not write the null terminators. + QPDF_DLL + void writeCStr(char const* cstr); + QPDF_DLL + void writeString(std::string const&); + // This allows *p << "x" << "y" but is not intended to be a general purpose << compatible with + // ostream and does not have local awareness or the ability to be "imbued" with properties. + QPDF_DLL + Pipeline& operator<<(char const* cstr); + QPDF_DLL + Pipeline& operator<<(std::string const&); + QPDF_DLL + Pipeline& operator<<(short); + QPDF_DLL + Pipeline& operator<<(int); + QPDF_DLL + Pipeline& operator<<(long); + QPDF_DLL + Pipeline& operator<<(long long); + QPDF_DLL + Pipeline& operator<<(unsigned short); + QPDF_DLL + Pipeline& operator<<(unsigned int); + QPDF_DLL + Pipeline& operator<<(unsigned long); + QPDF_DLL + Pipeline& operator<<(unsigned long long); + + // Overloaded write to reduce casting + QPDF_DLL + void write(char const* data, size_t len); + + protected: + QPDF_DLL + Pipeline* getNext(bool allow_null = false); + + Pipeline* + next() const noexcept + { + return next_; + } + std::string identifier; + + private: + Pipeline(Pipeline const&) = delete; + Pipeline& operator=(Pipeline const&) = delete; + + Pipeline* next_; +}; + +#endif // PIPELINE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Buffer.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Buffer.hh new file mode 100644 index 0000000..b3b7ed6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Buffer.hh @@ -0,0 +1,76 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_BUFFER_HH +#define PL_BUFFER_HH + +#include +#include + +#include +#include + +// This pipeline accumulates the data passed to it into a memory buffer. Each subsequent use of +// this buffer appends to the data accumulated so far. getBuffer() may be called only after calling +// finish() and before calling any subsequent write(). At that point, a dynamically allocated +// Buffer object is returned and the internal buffer is reset. The caller is responsible for +// deleting the returned Buffer. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it. +class QPDF_DLL_CLASS Pl_Buffer: public Pipeline +{ + public: + QPDF_DLL + Pl_Buffer(char const* identifier, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_Buffer() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + + // Each call to getBuffer() resets this object -- see notes above. + // The caller is responsible for deleting the returned Buffer object. See also + // getBufferSharedPointer() and getMallocBuffer(). + QPDF_DLL + Buffer* getBuffer(); + + // Same as getBuffer but wraps the result in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // getMallocBuffer behaves in the same was as getBuffer except the buffer is allocated with + // malloc(), making it suitable for use when calling from other languages. If there is no data, + // *buf is set to a null pointer and *len is set to 0. Otherwise, *buf is a buffer of size *len + // allocated with malloc(). It is the caller's responsibility to call free() on the buffer. + QPDF_DLL + void getMallocBuffer(unsigned char** buf, size_t* len); + + // Same as getBuffer but returns the result as a string. + QPDF_DLL + std::string getString(); + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Concatenate.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Concatenate.hh new file mode 100644 index 0000000..48a7ca8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Concatenate.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_CONCATENATE_HH +#define PL_CONCATENATE_HH + +#include + +// This pipeline will drop all regular finish calls rather than passing them onto next. To finish +// downstream streams, call manualFinish. This makes it possible to pipe multiple streams (e.g. +// with QPDFObjectHandle::pipeStreamData) to a downstream like Pl_Flate that can't handle multiple +// calls to finish(). +class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline +{ + public: + QPDF_DLL + Pl_Concatenate(char const* identifier, Pipeline* next); + + QPDF_DLL + ~Pl_Concatenate() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + + QPDF_DLL + void finish() override; + + // At the very end, call manualFinish to actually finish the rest of the pipeline. + QPDF_DLL + void manualFinish(); + + private: + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Concatenate; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::unique_ptr m{nullptr}; +}; + +#endif // PL_CONCATENATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Count.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Count.hh new file mode 100644 index 0000000..2189b81 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Count.hh @@ -0,0 +1,52 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_COUNT_HH +#define PL_COUNT_HH + +#include +#include + +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Count: public Pipeline +{ + public: + QPDF_DLL + Pl_Count(char const* identifier, Pipeline* next); + QPDF_DLL + ~Pl_Count() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + // Returns the number of bytes written + QPDF_DLL + qpdf_offset_t getCount() const; + // Returns the last character written, or '\0' if no characters have been written (in which case + // getCount() returns 0) + QPDF_DLL + unsigned char getLastChar() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_COUNT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_DCT.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_DCT.hh new file mode 100644 index 0000000..48f2594 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_DCT.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DCT_HH +#define PL_DCT_HH + +#include + +#include +#include + +// jpeglib.h must be included after cstddef or else it messes up the definition of size_t. +#include + +class QPDF_DLL_CLASS Pl_DCT: public Pipeline +{ + public: + // Constructor for decompressing image data + QPDF_DLL + Pl_DCT(char const* identifier, Pipeline* next); + + // Limit the memory used by jpeglib when decompressing data. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setMemoryLimit(long limit); + + // Limit the number of scans used by jpeglib when decompressing progressive jpegs. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setScanLimit(int limit); + + // Treat corrupt data as a runtime error rather than attempting to decompress regardless. This + // is the qpdf default behaviour. To attempt to decompress corrupt data set 'treat_as_error' to + // false. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setThrowOnCorruptData(bool treat_as_error); + + class QPDF_DLL_CLASS CompressConfig + { + public: + QPDF_DLL + CompressConfig() = default; + QPDF_DLL + virtual ~CompressConfig() = default; + virtual void apply(jpeg_compress_struct*) = 0; + }; + + QPDF_DLL + static std::unique_ptr + make_compress_config(std::function); + + // Constructor for compressing image data + QPDF_DLL + Pl_DCT( + char const* identifier, + Pipeline* next, + JDIMENSION image_width, + JDIMENSION image_height, + int components, + J_COLOR_SPACE color_space, + CompressConfig* config_callback = nullptr); + + QPDF_DLL + ~Pl_DCT() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void compress(void* cinfo); + QPDF_DLL_PRIVATE + void decompress(void* cinfo); + + enum action_e { a_compress, a_decompress }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_DCT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Discard.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Discard.hh new file mode 100644 index 0000000..b0073cd --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Discard.hh @@ -0,0 +1,41 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DISCARD_HH +#define PL_DISCARD_HH + +#include + +// This pipeline discards its output. It is an end-of-line pipeline (with no next). +// +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Discard: public Pipeline +{ + public: + QPDF_DLL + Pl_Discard(); + QPDF_DLL + ~Pl_Discard() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; +}; + +#endif // PL_DISCARD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Flate.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Flate.hh new file mode 100644 index 0000000..2347a91 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Flate.hh @@ -0,0 +1,126 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef PL_FLATE_HH +#define PL_FLATE_HH + +#include +#include +#include +#include +#include + +class QPDF_DLL_CLASS Pl_Flate: public Pipeline +{ + public: + static unsigned int const def_bufsize = 65536; + + enum action_e { a_inflate, a_deflate }; + + QPDF_DLL + Pl_Flate( + char const* identifier, + Pipeline* next, + action_e action, + unsigned int out_bufsize = def_bufsize); + QPDF_DLL + ~Pl_Flate() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_Flate instances. + QPDF_DLL + static unsigned long long memory_limit(); + QPDF_DLL + static void memory_limit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + // Globally set compression level from 1 (fastest, least + // compression) to 9 (slowest, most compression). Use -1 to set + // the default compression level. This is passed directly to zlib. + // This method returns a pointer to the current Pl_Flate object so + // you can create a pipeline with + // Pl_Flate(...)->setCompressionLevel(...) + QPDF_DLL + static void setCompressionLevel(int); + + QPDF_DLL + void setWarnCallback(std::function callback); + + // Returns true if qpdf was built with zopfli support. + QPDF_DLL + static bool zopfli_supported(); + + // Returns true if zopfli is enabled. Zopfli is enabled if QPDF_ZOPFLI is set to a value other + // than "disabled" and zopfli support is compiled in. + QPDF_DLL + static bool zopfli_enabled(); + + // If zopfli is supported, returns true. Otherwise, check the QPDF_ZOPFLI + // environment variable as follows: + // - "disabled" or "silent": return true + // - "force": qpdf_exit_error, throw an exception + // - Any other value: issue a warning, and return false + QPDF_DLL + static bool zopfli_check_env(QPDFLogger* logger = nullptr); + + private: + QPDF_DLL_PRIVATE + void handleData(unsigned char const* data, size_t len, int flush); + QPDF_DLL_PRIVATE + void checkError(char const* prefix, int error_code); + QPDF_DLL_PRIVATE + void warn(char const*, int error_code); + QPDF_DLL_PRIVATE + void finish_zopfli(); + + QPDF_DLL_PRIVATE + static int compression_level; + + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Flate; + + public: + Members(size_t out_bufsize, action_e action); + ~Members(); + + private: + Members(Members const&) = delete; + + std::shared_ptr outbuf; + size_t out_bufsize; + action_e action; + bool initialized; + void* zdata; + unsigned long long written{0}; + std::function callback; + std::unique_ptr zopfli_buf; + }; + + std::unique_ptr m; +}; + +#endif // PL_FLATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Function.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Function.hh new file mode 100644 index 0000000..081a4e1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_Function.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_FUNCTION_HH +#define PL_FUNCTION_HH + +#include + +#include + +// This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can +// be reused. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". +// +// It is okay to keep calling write() after a previous write throws an exception as long as the +// delegated function allows it. +class QPDF_DLL_CLASS Pl_Function: public Pipeline +{ + public: + typedef std::function writer_t; + + // The supplied function is called every time write is called. + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_t fn); + + // The supplied C-style function is called every time write is called. The udata option is + // passed into the function with each call. If the function returns a non-zero value, a runtime + // error is thrown. + typedef int (*writer_c_t)(unsigned char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata); + typedef int (*writer_c_char_t)(char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata); + + QPDF_DLL + ~Pl_Function() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_FUNCTION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_OStream.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_OStream.hh new file mode 100644 index 0000000..0f912f7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_OStream.hh @@ -0,0 +1,50 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_OSTREAM_HH +#define PL_OSTREAM_HH + +#include + +#include + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. +// +// This pipeline is reusable. +class QPDF_DLL_CLASS Pl_OStream: public Pipeline +{ + public: + // os is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_OStream(char const* identifier, std::ostream& os); + QPDF_DLL + ~Pl_OStream() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_OSTREAM_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_QPDFTokenizer.hh new file mode 100644 index 0000000..e26b856 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_QPDFTokenizer.hh @@ -0,0 +1,59 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_QPDFTOKENIZER_HH +#define PL_QPDFTOKENIZER_HH + +#include + +#include +#include +#include + +#include + +// Tokenize the incoming text using QPDFTokenizer and pass the tokens in turn to a +// QPDFObjectHandle::TokenFilter object. All bytes of incoming content will be included in exactly +// one token and passed downstream. +// +// This is a very low-level interface for working with token filters. Most code will want to use +// QPDFObjectHandle::filterPageContents or QPDFObjectHandle::addTokenFilter. See QPDFObjectHandle.hh +// for details. +class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline +{ + public: + // Whatever pipeline is provided as "next" will be set as the pipeline that the token filter + // writes to. If next is not provided, any output written by the filter will be discarded. + QPDF_DLL + Pl_QPDFTokenizer( + char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_QPDFTokenizer() override; + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_RunLength.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_RunLength.hh new file mode 100644 index 0000000..4fc91fa --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_RunLength.hh @@ -0,0 +1,60 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_RUNLENGTH_HH +#define PL_RUNLENGTH_HH + +#include + +class QPDF_DLL_CLASS Pl_RunLength: public Pipeline +{ + public: + enum action_e { a_encode, a_decode }; + + QPDF_DLL + Pl_RunLength(char const* identifier, Pipeline* next, action_e action); + QPDF_DLL + ~Pl_RunLength() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_RunLength instances. + QPDF_DLL + static void setMemoryLimit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void encode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void decode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void flush_encode(); + + enum state_e { st_top, st_copying, st_run }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_RUNLENGTH_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_StdioFile.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_StdioFile.hh new file mode 100644 index 0000000..4c70528 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_StdioFile.hh @@ -0,0 +1,51 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. + +#ifndef PL_STDIOFILE_HH +#define PL_STDIOFILE_HH + +#include + +#include + +// +// This pipeline is reusable. +// +class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline +{ + public: + // f is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_StdioFile(char const* identifier, FILE* f); + QPDF_DLL + ~Pl_StdioFile() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + std::unique_ptr m; +}; + +#endif // PL_STDIOFILE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_String.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_String.hh new file mode 100644 index 0000000..a907b44 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Pl_String.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_STRING_HH +#define PL_STRING_HH + +#include + +#include + +// This pipeline accumulates the data passed to it into a std::string, a reference to which is +// passed in at construction. Each subsequent use of this pipeline appends to the data accumulated +// so far. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". This makes it easy to stick +// this in front of another pipeline to capture data that is written to the other pipeline without +// interfering with when finish is called on the other pipeline and without having to put a +// Pl_Concatenate after it. +class QPDF_DLL_CLASS Pl_String: public Pipeline +{ + public: + QPDF_DLL + Pl_String(char const* identifier, Pipeline* next, std::string& s); + QPDF_DLL + ~Pl_String() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_STRING_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/PointerHolder.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/PointerHolder.hh new file mode 100644 index 0000000..2df2d25 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/PointerHolder.hh @@ -0,0 +1,245 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef POINTERHOLDER_HH +#define POINTERHOLDER_HH + +#define POINTERHOLDER_IS_SHARED_POINTER + +#ifndef POINTERHOLDER_TRANSITION +// 0 = no deprecation warnings, backward-compatible API +// 1 = make PointerHolder(T*) explicit +// 2 = warn for use of getPointer() and getRefcount() +// 3 = warn for all use of PointerHolder +// 4 = don't define PointerHolder at all +# define POINTERHOLDER_TRANSITION 4 +#endif // !defined(POINTERHOLDER_TRANSITION) + +#if POINTERHOLDER_TRANSITION < 4 + +// *** WHAT IS HAPPENING *** + +// In qpdf 11, PointerHolder was replaced with std::shared_ptr +// wherever it appeared in the qpdf API. The PointerHolder object is +// now derived from std::shared_ptr to provide a backward-compatible +// interface and is mutually assignable with std::shared_ptr. Code +// that uses containers of PointerHolder will require adjustment. + +// In qpdf 11, a backward-compatible PointerHolder was provided with a +// warning if POINTERHOLDER_TRANSITION was not defined. Starting in +// qpdf 12, PointerHolder is absent if POINTERHOLDER_TRANSITION is not +// defined. In a future version of qpdf, PointerHolder will be removed +// outright if it becomes inconvenient to keep it around. + +// *** HOW TO TRANSITION *** + +// The symbol POINTERHOLDER_TRANSITION can be defined to help you +// transition your code away from PointerHolder. You can define it +// before including any qpdf header files or including its definition +// in your build configuration. If not defined, it automatically gets +// defined to 4, which excludes PointerHolder entirely. + +// If you want to work gradually to transition your code away from +// PointerHolder, you can define POINTERHOLDER_TRANSITION and fix the +// code so it compiles without warnings and works correctly. If you +// want to be able to continue to support old qpdf versions at the +// same time, you can write code like this: + +// #ifndef POINTERHOLDER_IS_SHARED_POINTER +// ... use PointerHolder as before 10.6 +// #else +// ... use PointerHolder or shared_ptr as needed +// #endif + +// Each level of POINTERHOLDER_TRANSITION exposes differences between +// PointerHolder and std::shared_ptr. The easiest way to transition is +// to increase POINTERHOLDER_TRANSITION in steps of 1 so that you can +// test and handle changes incrementally. + +// POINTERHOLDER_TRANSITION = 1 +// +// PointerHolder has an implicit constructor that takes a T*, so +// you can replace a PointerHolder's pointer by directly assigning +// a T* to it or pass a T* to a function that expects a +// PointerHolder. std::shared_ptr does not have this (risky) +// behavior. When POINTERHOLDER_TRANSITION = 1, PointerHolder's T* +// constructor is declared explicit. For compatibility with +// std::shared_ptr, you can still assign nullptr to a PointerHolder. +// Constructing all your PointerHolder instances explicitly is +// backward compatible, so you can make this change without +// conditional compilation and still use the changes with older qpdf +// versions. +// +// Also defined is a make_pointer_holder method that acts like +// std::make_shared. You can use this as well, but it is not +// compatible with qpdf prior to 10.6 and not necessary with qpdf +// newer than 10.6.3. Like std::make_shared, make_pointer_holder +// can only be used when the constructor implied by its arguments is +// public. If you previously used this, you can replace it width +// std::make_shared now. + +// POINTERHOLDER_TRANSITION = 2 +// +// std::shared_ptr has get() and use_count(). PointerHolder has +// getPointer() and getRefcount(). In 10.6.0, get() and use_count() +// were added as well. When POINTERHOLDER_TRANSITION = 2, getPointer() +// and getRefcount() are deprecated. Fix deprecation warnings by +// replacing with get() and use_count(). This breaks compatibility +// with qpdf older than 10.6. Search for CONST BEHAVIOR for an +// additional note. +// +// Once your code is clean at POINTERHOLDER_TRANSITION = 2, the only +// remaining issues that prevent simple replacement of PointerHolder +// with std::shared_ptr are shared arrays and containers, and neither +// of these are used in the qpdf API. + +// POINTERHOLDER_TRANSITION = 3 +// +// Warn for all use of PointerHolder. This helps you remove all use +// of PointerHolder from your code and use std::shared_ptr instead. +// You will also have to transition any containers of PointerHolder in +// your code. + +// POINTERHOLDER_TRANSITION = 4 +// +// Suppress definition of the PointerHolder type entirely. This is +// the default behavior starting with qpdf 12. + +// CONST BEHAVIOR + +// PointerHolder has had a long-standing bug in its const behavior. +// const PointerHolder's getPointer() method returns a T const*. +// This is incorrect and is not how regular pointers or standard +// library smart pointers behave. Making a PointerHolder const +// should prevent reassignment of its pointer but not affect the thing +// it points to. For that, use PointerHolder. The new get() +// method behaves correctly in this respect and is therefore slightly +// different from getPointer(). This shouldn't break any correctly +// written code. If you are relying on the incorrect behavior, use +// PointerHolder instead. + +# include +# include + +template +class PointerHolder: public std::shared_ptr +{ + public: +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(std::shared_ptr other) : + std::shared_ptr(other) + { + } +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# if POINTERHOLDER_TRANSITION >= 1 + explicit +# endif // POINTERHOLDER_TRANSITION >= 1 +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(T* pointer = 0) : + std::shared_ptr(pointer) + { + } + // Create a shared pointer to an array +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(bool, T* pointer) : + std::shared_ptr(pointer, std::default_delete()) + { + } + + virtual ~PointerHolder() = default; + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T* + getPointer() + { + return this->get(); + } +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T const* + getPointer() const + { + return this->get(); + } + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + int + getRefcount() const + { + return static_cast(this->use_count()); + } + + PointerHolder& + operator=(decltype(nullptr)) + { + std::shared_ptr::operator=(nullptr); + return *this; + } + T const& + operator*() const + { + return *(this->get()); + } + T& + operator*() + { + return *(this->get()); + } + + T const* + operator->() const + { + return this->get(); + } + T* + operator->() + { + return this->get(); + } +}; + +template +inline PointerHolder +make_pointer_holder(_Args&&... __args) +{ + return PointerHolder(new T(__args...)); +} + +template +PointerHolder +make_array_pointer_holder(size_t n) +{ + return PointerHolder(true, new T[n]); +} + +#endif // POINTERHOLDER_TRANSITION < 4 +#endif // POINTERHOLDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QIntC.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QIntC.hh new file mode 100644 index 0000000..cef8aca --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QIntC.hh @@ -0,0 +1,310 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QINTC_HH +#define QINTC_HH + +#include +#include +#include +#include +#include +#include +#include +#include + +// This namespace provides safe integer conversion that detects +// overflows. It uses short, cryptic names for brevity. + +namespace QIntC // QIntC = qpdf Integer Conversion +{ + // to_u is here for backward-compatibility from before we required + // C++-11. + template + class to_u + { + public: + typedef typename std::make_unsigned::type type; + }; + + // Basic IntConverter class, which converts an integer from the + // From class to one of the To class if it can be done safely and + // throws a range_error otherwise. This class is specialized for + // each permutation of signed/unsigned for the From and To + // classes. + template < + typename From, + typename To, + bool From_signed = std::numeric_limits::is_signed, + bool To_signed = std::numeric_limits::is_signed> + class IntConverter + { + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both unsigned. + if (i > std::numeric_limits::max()) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both signed. + if ((i < std::numeric_limits::min()) || (i > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is signed, and To is unsigned. If i > 0, it's safe to + // convert it to the corresponding unsigned type and to + // compare with To's max. + auto ii = static_cast::type>(i); + if ((i < 0) || (ii > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is unsigned, and to is signed. Convert To's max to the + // unsigned version of To and compare i against that. + auto maxval = static_cast::type>(std::numeric_limits::max()); + if (i > maxval) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + // Specific converters. The return type of each function must match + // the second template parameter to IntConverter. + template + inline char + to_char(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned char + to_uchar(T const& i) + { + return IntConverter::convert(i); + } + + template + inline short + to_short(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned short + to_ushort(T const& i) + { + return IntConverter::convert(i); + } + + template + inline int + to_int(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned int + to_uint(T const& i) + { + return IntConverter::convert(i); + } + + template + inline size_t + to_size(T const& i) + { + return IntConverter::convert(i); + } + + template + inline qpdf_offset_t + to_offset(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long + to_long(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long + to_ulong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long long + to_longlong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long long + to_ulonglong(T const& i) + { + return IntConverter::convert(i); + } + + template + void + range_check_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::max() - cur) < delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::min() - cur) > delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check(T const& cur, T const& delta) + { + if ((delta > 0) != (cur > 0)) { + return; + } + QIntC::range_check_error(cur, delta); + } + + template + void + range_check_subtract_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::min() + delta) > cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur + << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::max() + delta) < cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check_subtract(T const& cur, T const& delta) + { + if ((delta >= 0) == (cur >= 0)) { + return; + } + QIntC::range_check_subtract_error(cur, delta); + } +}; // namespace QIntC + +#endif // QINTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDF.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDF.hh new file mode 100644 index 0000000..5f990b7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDF.hh @@ -0,0 +1,804 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_HH +#define QPDF_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFLogger; + +class QPDF +{ + public: + // Get the current version of the QPDF software. See also qpdf/DLL.h + QPDF_DLL + static std::string const& QPDFVersion(); + + QPDF_DLL + QPDF(); + QPDF_DLL + ~QPDF(); + + QPDF_DLL + static std::shared_ptr create(); + + // Associate a file with a QPDF object and do initial parsing of the file. PDF objects are not + // read until they are needed. A QPDF object may be associated with only one file in its + // lifetime. This method must be called before any methods that potentially ask for information + // about the PDF file are called. Prior to calling this, the only methods that are allowed are + // those that set parameters. If the input file is not encrypted, either a null password or an + // empty password can be used. If the file is encrypted, either the user password or the owner + // password may be supplied. The method setPasswordIsHexKey may be called prior to calling this + // method or any of the other process methods to force the password to be interpreted as a raw + // encryption key. See comments on setPasswordIsHexKey for more information. + QPDF_DLL + void processFile(char const* filename, char const* password = nullptr); + + // Parse a PDF from a stdio FILE*. The FILE must be open in binary mode and must be seekable. + // It may be open read only. This works exactly like processFile except that the PDF file is + // read from an already opened FILE*. If close_file is true, the file will be closed at the + // end. Otherwise, the caller is responsible for closing the file. + QPDF_DLL + void processFile( + char const* description, FILE* file, bool close_file, char const* password = nullptr); + + // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except + // that the PDF file is in memory instead of on disk. The description appears in any warning or + // error message in place of the file name. The buffer is owned by the caller and must remain + // valid for the lifetime of the QPDF object. + QPDF_DLL + void processMemoryFile( + char const* description, char const* buf, size_t length, char const* password = nullptr); + + // Parse a PDF file loaded from a custom InputSource. If you have your own method of retrieving + // a PDF file, you can subclass InputSource and use this method. + QPDF_DLL + void processInputSource(std::shared_ptr, char const* password = nullptr); + + // Create a PDF from an input source that contains JSON as written by writeJSON (or qpdf + // --json-output, version 2 or higher). The JSON must be a complete representation of a PDF. See + // "qpdf JSON" in the manual for details. The input JSON may be arbitrarily large. QPDF does not + // load stream data into memory for more than one stream at a time, even if the stream data is + // specified inline. + QPDF_DLL + void createFromJSON(std::string const& json_file); + QPDF_DLL + void createFromJSON(std::shared_ptr); + + // Update a PDF from an input source that contains JSON in the same format as is written by + // writeJSON (or qpdf --json-output, version 2 or higher). Objects in the PDF and not in the + // JSON are not modified. See "qpdf JSON" in the manual for details. As with createFromJSON, the + // input JSON may be arbitrarily large. + QPDF_DLL + void updateFromJSON(std::string const& json_file); + QPDF_DLL + void updateFromJSON(std::shared_ptr); + + // Write qpdf JSON format to the pipeline "p". The only supported version is 2. The finish() + // method is not called on the pipeline. + // + // The decode_level parameter controls which streams are uncompressed in the JSON. Use + // qpdf_dl_none to preserve all stream data exactly as it appears in the input. The possible + // values for json_stream_data can be found in qpdf/Constants.h and correspond to the + // --json-stream-data command-line argument. If json_stream_data is qpdf_sj_file, file_prefix + // must be specified. Each stream will be written to a file whose path is constructed by + // appending "-nnn" to file_prefix, where "nnn" is the object number (not zero-filled). If + // wanted_objects is empty, write all objects. Otherwise, write only objects whose keys are in + // wanted_objects. Keys may be either "trailer" or of the form "obj:n n R". Invalid keys are + // ignored. This corresponds to the --json-object command-line argument. + // + // QPDF is efficient with regard to memory when writing, allowing you to write arbitrarily large + // PDF files to a pipeline. You can use a pipeline like Pl_Buffer or Pl_String to capture the + // JSON output in memory, but do so with caution as this will allocate enough memory to hold the + // entire PDF file. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // This version of writeJSON enables writing only the "qpdf" key of an in-progress dictionary. + // If the value of "complete" is true, a complete JSON object containing only the "qpdf" key is + // written to the pipeline. If the value of "complete" is false, the "qpdf" key and its value + // are written to the pipeline assuming that a dictionary is already open. The parameter + // first_key indicates whether this is the first key in an in-progress dictionary. It will be + // set to false by writeJSON. The "qpdf" key and value are written as if at depth 1 in a + // prettified JSON output. Remaining arguments are the same as the above version. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + bool complete, + bool& first_key, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // Close or otherwise release the input source. Once this has been called, no other methods of + // qpdf can be called safely except for getWarnings and anyWarnings(). After this has been + // called, it is safe to perform operations on the input file such as deleting or renaming it. + QPDF_DLL + void closeInputSource(); + + // For certain forensic or investigatory purposes, it may sometimes be useful to specify the + // encryption key directly, even though regular PDF applications do not provide a way to do + // this. Calling setPasswordIsHexKey(true) before calling any of the process methods will bypass + // the normal encryption key computation or recovery mechanisms and interpret the bytes in the + // password as a hex-encoded encryption key. Note that we hex-encode the key because it may + // contain null bytes and therefore can't be represented in a char const*. + QPDF_DLL + void setPasswordIsHexKey(bool); + + // Create a QPDF object for an empty PDF. This PDF has no pages or objects other than a minimal + // trailer, a document catalog, and a /Pages tree containing zero pages. Pages and other + // objects can be added to the file in the normal way, and the trailer and document catalog can + // be mutated. Calling this method is equivalent to calling processFile on an equivalent PDF + // file. See the pdf-create.cc example for a demonstration of how to use this method to create + // a PDF file from scratch. + QPDF_DLL + void emptyPDF(); + + // From 10.1: register a new filter implementation for a specific stream filter. You can add + // your own implementations for new filter types or override existing ones provided by the + // library. Registered stream filters are used for decoding only as you can override encoding + // with stream data providers. For example, you could use this method to add support for one of + // the other filter types by using additional third-party libraries that qpdf does not presently + // use. The standard filters are implemented using QPDFStreamFilter classes. + QPDF_DLL + static void registerStreamFilter( + std::string const& filter_name, std::function()> factory); + + // Parameter settings + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // Note that no normal QPDF operations generate output to standard output, so for applications + // that just wish to avoid creating output for warnings and don't call any check functions, + // calling setSuppressWarnings(true) is sufficient. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // If true, ignore any cross-reference streams in a hybrid file (one that contains both + // cross-reference streams and cross-reference tables). This can be useful for testing to + // ensure that a hybrid file would work with an older reader. + QPDF_DLL + void setIgnoreXRefStreams(bool); + + // By default, any warnings are issued to std::cerr or the error stream specified in a call to + // setOutputStreams as they are encountered. If this method is called with a true value, + // reporting of warnings is suppressed. You may still retrieve warnings by calling getWarnings. + QPDF_DLL + void setSuppressWarnings(bool); + + // Set the maximum number of warnings. A QPDFExc is thrown if the limit is exceeded. + QPDF_DLL + void setMaxWarnings(size_t); + + // By default, QPDF will try to recover if it finds certain types of errors in PDF files. If + // turned off, it will throw an exception on the first such problem it finds without attempting + // recovery. + QPDF_DLL + void setAttemptRecovery(bool); + + // Tell other QPDF objects that streams copied from this QPDF need to be fully copied when + // copyForeignObject is called on them. Calling setIgnoreXRefStreams(true) on a QPDF object + // makes it possible for the object and its input source to disappear before streams copied from + // it are written with the destination QPDF object. Confused? Ordinarily, if you are going to + // copy objects from a source QPDF object to a destination QPDF object using copyForeignObject + // or addPage, the source object's input source must stick around until after the destination + // PDF is written. If you call this method on the source QPDF object, it sends a signal to the + // destination object that it must fully copy the stream data when copyForeignObject. It will do + // this by making a copy in RAM. Ordinarily the stream data is copied lazily to avoid + // unnecessary duplication of the stream data. Note that the stream data is copied into RAM only + // once regardless of how many objects the stream is copied into. The result is that, if you + // called setImmediateCopyFrom(true) on a given QPDF object prior to copying any of its streams, + // you do not need to keep it or its input source around after copying its objects to another + // QPDF. This is true even if the source streams use StreamDataProvider. Note that this method + // is called on the QPDF object you are copying FROM, not the one you are copying to. The + // reasoning for this is that there's no reason a given QPDF may not get objects copied to it + // from a variety of other objects, some transient and some not. Since what's relevant is + // whether the source QPDF is transient, the method must be called on the source QPDF, not the + // destination one. This method will make a copy of the stream in RAM, so be sure you have + // enough memory to simultaneously hold all the streams you're copying. + QPDF_DLL + void setImmediateCopyFrom(bool); + + // Other public methods + + // Return the list of warnings that have been issued so far and clear the list. This method may + // be called even if processFile throws an exception. Note that if setSuppressWarnings was not + // called or was called with a false value, any warnings retrieved here will have already been + // output. + QPDF_DLL + std::vector getWarnings(); + + // Indicate whether any warnings have been issued so far. Does not clear the list of warnings. + QPDF_DLL + bool anyWarnings() const; + + // Indicate the number of warnings that have been issued since the last call to getWarnings. + // Does not clear the list of warnings. + QPDF_DLL + size_t numWarnings() const; + + // Return an application-scoped unique ID for this QPDF object. This is not a globally unique + // ID. It is constructed using a timestamp and a random number and is intended to be unique + // among QPDF objects that are created by a single run of an application. While it's very likely + // that these are actually globally unique, it is not recommended to use them for long-term + // purposes. + QPDF_DLL + unsigned long long getUniqueId() const; + + // Issue a warning on behalf of this QPDF object. It will be emitted with other warnings, + // following warning suppression rules, and it will be available with getWarnings(). + QPDF_DLL + void warn(QPDFExc const& e); + // Same as above but creates the QPDFExc object using the arguments passed to warn. The filename + // argument to QPDFExc is omitted. This method uses the filename associated with the QPDF + // object. + QPDF_DLL + void warn( + qpdf_error_code_e error_code, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // Return the filename associated with the QPDF object. + QPDF_DLL + std::string getFilename() const; + // Return PDF Version and extension level together as a PDFVersion object + QPDF_DLL + PDFVersion getVersionAsPDFVersion(); + // Return just the PDF version from the file + QPDF_DLL + std::string getPDFVersion() const; + QPDF_DLL + int getExtensionLevel(); + QPDF_DLL + QPDFObjectHandle getTrailer(); + QPDF_DLL + QPDFObjectHandle getRoot(); + QPDF_DLL + std::map getXRefTable(); + + // Public factory methods + + // Create a new stream. A subsequent call must be made to replaceStreamData() to provide data + // for the stream. The stream's dictionary may be retrieved by calling getDict(), and the + // resulting dictionary may be modified. Alternatively, you can create a new dictionary and + // call replaceDict to install it. + QPDF_DLL + QPDFObjectHandle newStream(); + + // Create a new stream. Use the given buffer as the stream data. The stream dictionary's + // /Length key will automatically be set to the size of the data buffer. If additional keys are + // required, the stream's dictionary may be retrieved by calling getDict(), and the resulting + // dictionary may be modified. This method is just a convenient wrapper around the newStream() + // and replaceStreamData(). It is a convenience methods for streams that require no parameters + // beyond the stream length. Note that you don't have to deal with compression yourself if you + // use QPDFWriter. By default, QPDFWriter will automatically compress uncompressed stream data. + // Example programs are provided that illustrate this. + QPDF_DLL + QPDFObjectHandle newStream(std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + QPDF_DLL + QPDFObjectHandle newStream(std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. + QPDF_DLL + QPDFObjectHandle newReserved(); + QPDF_DLL + QPDFObjectHandle newIndirectNull(); + + // Install this object handle as an indirect object and return an indirect reference to it. + QPDF_DLL + QPDFObjectHandle makeIndirectObject(QPDFObjectHandle); + + // Retrieve an object by object ID and generation. Returns an indirect reference to it. The + // getObject() methods were added for qpdf 11. + QPDF_DLL + QPDFObjectHandle getObject(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObject(int objid, int generation); + // These are older methods, but there is no intention to deprecate + // them. + QPDF_DLL + QPDFObjectHandle getObjectByObjGen(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObjectByID(int objid, int generation); + + // Replace the object with the given object id with the given object. The object handle passed + // in must be a direct object, though it may contain references to other indirect objects within + // it. Prior to qpdf 10.2.1, after calling this method, existing QPDFObjectHandle instances that + // pointed to the original object still pointed to the original object, resulting in confusing + // and incorrect behavior. This was fixed in 10.2.1, so existing QPDFObjectHandle objects will + // start pointing to the newly replaced object. Note that replacing an object with + // QPDFObjectHandle::newNull() effectively removes the object from the file since a non-existent + // object is treated as a null object. To replace a reserved object, call replaceReserved + // instead. + QPDF_DLL + void replaceObject(QPDFObjGen og, QPDFObjectHandle); + QPDF_DLL + void replaceObject(int objid, int generation, QPDFObjectHandle); + + // Swap two objects given by ID. Prior to qpdf 10.2.1, existing QPDFObjectHandle instances that + // reference them objects not notice the swap, but this was fixed in 10.2.1. + QPDF_DLL + void swapObjects(QPDFObjGen og1, QPDFObjGen og2); + QPDF_DLL + void swapObjects(int objid1, int generation1, int objid2, int generation2); + + // Replace a reserved object. This is a wrapper around replaceObject but it guarantees that the + // underlying object is a reserved object or a null object. After this call, reserved will + // be a reference to replacement. + QPDF_DLL + void replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement); + + // Copy an object from another QPDF to this one. Starting with qpdf version 8.3.0, it is no + // longer necessary to keep the original QPDF around after the call to copyForeignObject as long + // as the source of any copied stream data is still available. Usually this means you just have + // to keep the input file around, not the QPDF object. The exception to this is if you copy a + // stream that gets its data from a QPDFObjectHandle::StreamDataProvider. In this case only, the + // original stream's QPDF object must stick around because the QPDF object is itself the source + // of the original stream data. For a more in-depth discussion, please see the TODO file. + // Starting in 8.4.0, you can call setImmediateCopyFrom(true) on the SOURCE QPDF object (the one + // you're copying FROM). If you do this prior to copying any of its objects, then neither the + // source QPDF object nor its input source needs to stick around at all regardless of the + // source. The cost is that the stream data is copied into RAM at the time copyForeignObject is + // called. See setImmediateCopyFrom for more information. + // + // The return value of this method is an indirect reference to the copied object in this file. + // This method is intended to be used to copy non-page objects. To copy page objects, pass the + // foreign page object directly to addPage (or addPageAt). If you copy objects that contain + // references to pages, you should copy the pages first using addPage(At). Otherwise references + // to the pages that have not been copied will be replaced with nulls. It is possible to use + // copyForeignObject on page objects if you are not going to use them as pages. Doing so copies + // the object normally but does not update the page structure. For example, it is a valid use + // case to use copyForeignObject for a page that you are going to turn into a form XObject, + // though you can also use QPDFPageObjectHelper::getFormXObjectForPage for that purpose. + // + // When copying objects with this method, object structure will be preserved, so all indirectly + // referenced indirect objects will be copied as well. This includes any circular references + // that may exist. The QPDF object keeps a record of what has already been copied, so shared + // objects will not be copied multiple times. This also means that if you mutate an object that + // has already been copied and try to copy it again, it won't work since the modified object + // will not be recopied. Therefore, you should do all mutation on the original file that you + // are going to do before you start copying its objects to a new file. + QPDF_DLL + QPDFObjectHandle copyForeignObject(QPDFObjectHandle foreign); + + // Encryption support + + enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes, e_aesv3 }; + + // To be removed from the public API in qpdf 13. See + // . + class EncryptionData + { + public: + // This class holds data read from the encryption dictionary. + EncryptionData( + int V, + int R, + int Length_bytes, + int P, + std::string const& O, + std::string const& U, + std::string const& OE, + std::string const& UE, + std::string const& Perms, + std::string const& id1, + bool encrypt_metadata) : + V(V), + R(R), + Length_bytes(Length_bytes), + P(P), + O(O), + U(U), + OE(OE), + UE(UE), + Perms(Perms), + id1(id1), + encrypt_metadata(encrypt_metadata) + { + } + + int getV() const; + int getR() const; + int getLengthBytes() const; + int getP() const; + std::string const& getO() const; + std::string const& getU() const; + std::string const& getOE() const; + std::string const& getUE() const; + std::string const& getPerms() const; + std::string const& getId1() const; + bool getEncryptMetadata() const; + + void setO(std::string const&); + void setU(std::string const&); + void setV5EncryptionParameters( + std::string const& O, + std::string const& OE, + std::string const& U, + std::string const& UE, + std::string const& Perms); + + private: + EncryptionData(EncryptionData const&) = delete; + EncryptionData& operator=(EncryptionData const&) = delete; + + int V; + int R; + int Length_bytes; + int P; + std::string O; + std::string U; + std::string OE; + std::string UE; + std::string Perms; + std::string id1; + bool encrypt_metadata; + }; + QPDF_DLL + bool isEncrypted() const; + + QPDF_DLL + bool isEncrypted(int& R, int& P); + + QPDF_DLL + bool isEncrypted( + int& R, + int& P, + int& V, + encryption_method_e& stream_method, + encryption_method_e& string_method, + encryption_method_e& file_method); + + QPDF_DLL + bool ownerPasswordMatched() const; + + QPDF_DLL + bool userPasswordMatched() const; + + // Encryption permissions -- not enforced by QPDF + QPDF_DLL + bool allowAccessibility(); + QPDF_DLL + bool allowExtractAll(); + QPDF_DLL + bool allowPrintLowRes(); + QPDF_DLL + bool allowPrintHighRes(); + QPDF_DLL + bool allowModifyAssembly(); + QPDF_DLL + bool allowModifyForm(); + QPDF_DLL + bool allowModifyAnnotation(); + QPDF_DLL + bool allowModifyOther(); + QPDF_DLL + bool allowModifyAll(); + + // Helper function to trim padding from user password. Calling trim_user_password on the result + // of getPaddedUserPassword gives getTrimmedUserPassword's result. + QPDF_DLL + static void trim_user_password(std::string& user_password); + QPDF_DLL + static std::string compute_data_key( + std::string const& encryption_key, + int objid, + int generation, + bool use_aes, + int encryption_V, + int encryption_R); + + // To be removed in qpdf 13. See . + [[deprecated("to be removed in qpdf 13")]] + QPDF_DLL static std::string + compute_encryption_key(std::string const& password, EncryptionData const& data); + + QPDF_DLL + static void compute_encryption_O_U( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& O, + std::string& U); + QPDF_DLL + static void compute_encryption_parameters_V5( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& encryption_key, + std::string& O, + std::string& U, + std::string& OE, + std::string& UE, + std::string& Perms); + // Return the full user password as stored in the PDF file. For files encrypted with 40-bit or + // 128-bit keys, the user password can be recovered when the file is opened using the owner + // password. This is not possible with newer encryption formats. If you are attempting to + // recover the user password in a user-presentable form, call getTrimmedUserPassword() instead. + QPDF_DLL + std::string const& getPaddedUserPassword() const; + // Return human-readable form of user password subject to same limitations as + // getPaddedUserPassword(). + QPDF_DLL + std::string getTrimmedUserPassword() const; + // Return the previously computed or retrieved encryption key for this file + QPDF_DLL + std::string getEncryptionKey() const; + // Remove security restrictions associated with digitally signed files. From qpdf 11.7.0, this + // is called by QPDFAcroFormDocumentHelper::disableDigitalSignatures and is more useful when + // called from there than when just called by itself. + QPDF_DLL + void removeSecurityRestrictions(); + + // Linearization support + + // Returns true iff the file starts with a linearization parameter dictionary. Does no + // additional validation. + QPDF_DLL + bool isLinearized(); + + // Performs various sanity checks on a linearized file. Return true if no errors or warnings. + // Otherwise, return false and output errors and warnings to the default output stream + // (std::cout or whatever is configured in the logger). It is recommended for linearization + // errors to be treated as warnings. + QPDF_DLL + bool checkLinearization(); + + // Calls checkLinearization() and, if possible, prints normalized contents of some of the hints + // tables to the default output stream. Normalization includes adding min values to delta values + // and adjusting offsets based on the location and size of the primary hint stream. + QPDF_DLL + void showLinearizationData(); + + // Shows the contents of the cross-reference table + QPDF_DLL + void showXRefTable(); + + // Starting from qpdf 11.0 user code should not need to call this method. Before 11.0 this + // method was used to detect all indirect references to objects that don't exist and resolve + // them by replacing them with null, which is how the PDF spec says to interpret such dangling + // references. This method is called automatically when you try to add any new objects, if you + // call getAllObjects, and before a file is written. The qpdf object caches whether it has run + // this to avoid running it multiple times. Before 11.2.1 you could pass true to force it to run + // again if you had explicitly added new objects that may have additional dangling references. + QPDF_DLL + void fixDanglingReferences(bool force = false); + + // Return the approximate number of indirect objects. It is/ approximate because not all objects + // in the file are preserved in all cases, and gaps in object numbering are not preserved. + QPDF_DLL + size_t getObjectCount(); + + // Returns a list of indirect objects for every object in the xref table. Useful for discovering + // objects that are not otherwise referenced. + QPDF_DLL + std::vector getAllObjects(); + + // Optimization support -- see doc/optimization. Implemented in QPDF_optimization.cc + + // The object_stream_data map maps from a "compressed" object to the object stream that contains + // it. This enables optimize to populate the object <-> user maps with only uncompressed + // objects. If allow_changes is false, an exception will be thrown if any changes are made + // during the optimization process. This is available so that the test suite can make sure that + // a linearized file is already optimized. When called in this way, optimize() still populates + // the object <-> user maps. The optional skip_stream_parameters parameter, if present, is + // called for each stream object. The function should return 2 if optimization should discard + // /Length, /Filter, and /DecodeParms; 1 if it should discard /Length, and 0 if it should + // preserve all keys. This is used by QPDFWriter to avoid creation of dangling objects for + // stream dictionary keys it will be regenerating. + [[deprecated("Unused - see release notes for qpdf 12.1.0")]] QPDF_DLL void optimize( + std::map const& object_stream_data, + bool allow_changes = true, + std::function skip_stream_parameters = nullptr); + + // Traverse page tree return all /Page objects. It also detects and resolves cases in which the + // same /Page object is duplicated. For efficiency, this method returns a const reference to an + // internal vector of pages. Calls to addPage, addPageAt, and removePage safely update this, but + // direct manipulation of the pages tree or pushing inheritable objects to the page level may + // invalidate it. See comments for updateAllPagesCache() for additional notes. Newer code should + // use QPDFPageDocumentHelper::getAllPages instead. The decision to expose this internal cache + // was arguably incorrect, but it is being left here for compatibility. It is, however, + // completely safe to use this for files that you are not modifying. + QPDF_DLL + std::vector const& getAllPages(); + + QPDF_DLL + bool everCalledGetAllPages() const; + QPDF_DLL + bool everPushedInheritedAttributesToPages() const; + + // These methods, given a page object or its object/generation number, returns the 0-based index + // into the array returned by getAllPages() for that page. An exception is thrown if the page is + // not found. + QPDF_DLL + int findPage(QPDFObjGen og); + QPDF_DLL + int findPage(QPDFObjectHandle& page); + + // This method synchronizes QPDF's cache of the page structure with the actual /Pages tree. If + // you restrict changes to the /Pages tree, including addition, removal, or replacement of pages + // or changes to any /Pages objects, to calls to these page handling APIs, you never need to + // call this method. If you modify /Pages structures directly, you must call this method + // afterwards. This method updates the internal list of pages, so after calling this method, + // any previous references returned by getAllPages() will be valid again. It also resets any + // state about having pushed inherited attributes in /Pages objects down to the pages, so if you + // add any inheritable attributes to a /Pages object, you should also call this method. + QPDF_DLL + void updateAllPagesCache(); + + // Legacy handling API. These methods are not going anywhere, and you should feel free to + // continue using them if it simplifies your code. Newer code should make use of + // QPDFPageDocumentHelper instead as future page handling methods will be added there. The + // functionality and specification of these legacy methods is identical to the identically named + // methods there, except that these versions use QPDFObjectHandle instead of + // QPDFPageObjectHelper, so please see comments in that file for descriptions. There are + // subtleties you need to know about, so please look at the comments there. + QPDF_DLL + void pushInheritedAttributesToPage(); + QPDF_DLL + void addPage(QPDFObjectHandle newpage, bool first); + QPDF_DLL + void addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage); + QPDF_DLL + void removePage(QPDFObjectHandle page); + // End legacy page helpers + + // End of the public API. The following classes and methods are for qpdf internal use only. + + class Doc; + + inline Doc& doc(); + + // For testing only -- do not add to DLL + static bool test_json_validators(); + + private: + // It has never been safe to copy QPDF objects as there is code in the library that assumes + // there are no copies of a QPDF object. Copying QPDF objects was not prevented by the API until + // qpdf 11. If you have been copying QPDF objects, use std::shared_ptr instead. From qpdf + // 11, you can use QPDF::create to create them. + QPDF(QPDF const&) = delete; + QPDF& operator=(QPDF const&) = delete; + + static std::string const qpdf_version; + + class ObjCache; + class EncryptionParameters; + class StringDecrypter; + class ResolveRecorder; + class JSONReactor; + + void removeObject(QPDFObjGen og); + + // Calls finish() on the pipeline when done but does not delete it + bool pipeStreamData( + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + static bool pipeStreamData( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + + // methods to support encryption -- implemented in QPDF_encryption.cc + void initializeEncryption(); + static std::string + getKeyForObject(std::shared_ptr encp, QPDFObjGen og, bool use_aes); + void decryptString(std::string&, QPDFObjGen og); + static void decryptStream( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + Pipeline*& pipeline, + QPDFObjGen og, + QPDFObjectHandle& stream_dict, + bool is_root_metadata, + std::unique_ptr& heap); + + // JSON import + void importJSON(std::shared_ptr, bool must_be_complete); + + class Members; + + // Keep all member variables inside the Members object, which we dynamically allocate. This + // makes it possible to add new private members without breaking binary compatibility. + std::unique_ptr m; +}; + +#endif // QPDF_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFAcroFormDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFAcroFormDocumentHelper.hh new file mode 100644 index 0000000..935e161 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFAcroFormDocumentHelper.hh @@ -0,0 +1,234 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFACROFORMDOCUMENTHELPER_HH +#define QPDFACROFORMDOCUMENTHELPER_HH + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +// This document helper is intended to help with operations on interactive forms. Here are the key +// things to know: + +// * The PDF specification talks about interactive forms and also about form XObjects. While form +// XObjects appear in parts of interactive forms, this class is concerned about interactive forms, +// not form XObjects. +// +// * Interactive forms are discussed in the PDF Specification (ISO PDF 32000-1:2008) section 12.7. +// Also relevant is the section about Widget annotations. Annotations are discussed in section +// 12.5 with annotation dictionaries discussed in 12.5.1. Widget annotations are discussed +// specifically in section 12.5.6.19. +// +// * What you need to know about the structure of interactive forms in PDF files: +// +// - The document catalog contains the key "/AcroForm" which contains a list of fields. Fields are +// represented as a tree structure much like pages. Nodes in the fields tree may contain other +// fields. Fields may inherit values of many of their attributes from ancestors in the tree. +// +// - Fields may also have children that are widget annotations. As a special case, and a cause of +// considerable confusion, if a field has a single annotation as a child, the annotation +// dictionary may be merged with the field dictionary. In that case, the field and the +// annotation are in the same object. Note that, while field dictionary attributes are +// inherited, annotation dictionary attributes are not. +// +// - A page dictionary contains a key called "/Annots" which contains a simple list of +// annotations. For any given annotation of subtype "/Widget", you should encounter that +// annotation in the "/Annots" dictionary of a page, and you should also be able to reach it by +// traversing through the "/AcroForm" dictionary from the document catalog. In the simplest case +// (and also a very common case), a form field's widget annotation will be merged with the field +// object, and the object will appear directly both under "/Annots" in the page dictionary and +// under "/Fields" in the "/AcroForm" dictionary. In a more complex case, you may have to trace +// through various "/Kids" elements in the "/AcroForm" field entry until you find the annotation +// dictionary. +class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFAcroFormDocumentHelper& get(QPDF& qpdf); + + // Re-validate the AcroForm structure. This is useful if you have modified the structure of the + // AcroForm dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFAcroFormDocumentHelper(QPDF&); + + ~QPDFAcroFormDocumentHelper() override = default; + + // This class lazily creates an internal cache of the mapping among form fields, annotations, + // and pages. Methods within this class preserve the validity of this cache. However, if you + // modify pages' annotation dictionaries, the document's /AcroForm dictionary, or any form + // fields manually in a way that alters the association between forms, fields, annotations, and + // pages, it may cause this cache to become invalid. This method marks the cache invalid and + // forces it to be regenerated the next time it is needed. + QPDF_DLL + void invalidateCache(); + + QPDF_DLL + bool hasAcroForm(); + + // Add a form field, initializing the document's AcroForm dictionary if needed, updating the + // cache if necessary. Note that you are adding fields that are copies of other fields, this + // method may result in multiple fields existing with the same qualified name, which can have + // unexpected side effects. In that case, you should use addAndRenameFormFields() instead. + QPDF_DLL + void addFormField(QPDFFormFieldObjectHelper); + + // Add a collection of form fields making sure that their fully qualified names don't conflict + // with already present form fields. Fields within the collection of new fields that have the + // same name as each other will continue to do so. + QPDF_DLL + void addAndRenameFormFields(std::vector fields); + + // Remove fields from the fields array + QPDF_DLL + void removeFormFields(std::set const&); + + // Set the name of a field, updating internal records of field names. Name should be UTF-8 + // encoded. + QPDF_DLL + void setFormFieldName(QPDFFormFieldObjectHelper, std::string const& name); + + // Return a vector of all terminal fields in a document. Terminal fields are fields that have no + // children that are also fields. Terminal fields may still have children that are annotations. + // Intermediate nodes in the fields tree are not included in this list, but you can still reach + // them through the getParent method of the field object helper. + QPDF_DLL + std::vector getFormFields(); + + // Return all the form fields that have the given fully-qualified name and also have an explicit + // "/T" attribute. For this information to be accurate, any changes to field names must be done + // through setFormFieldName() above. + QPDF_DLL + std::set getFieldsWithQualifiedName(std::string const& name); + + // Return the annotations associated with a terminal field. Note that in the case of a field + // having a single annotation, the underlying object will typically be the same as the + // underlying object for the field. + QPDF_DLL + std::vector getAnnotationsForField(QPDFFormFieldObjectHelper); + + // Return annotations of subtype /Widget for a page. + QPDF_DLL + std::vector getWidgetAnnotationsForPage(QPDFPageObjectHelper); + + // Return top-level form fields for a page. + QPDF_DLL + std::vector getFormFieldsForPage(QPDFPageObjectHelper); + + // Return the terminal field that is associated with this annotation. If the annotation + // dictionary is merged with the field dictionary, the underlying object will be the same, but + // this is not always the case. Note that if you call this method with an annotation that is not + // a widget annotation, there will not be an associated field, and this method will return a + // helper associated with a null object (isNull() == true). + QPDF_DLL + QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper); + + // Return the current value of /NeedAppearances. If /NeedAppearances is missing, return false as + // that is how PDF viewers are supposed to interpret it. + QPDF_DLL + bool getNeedAppearances(); + + // Indicate whether appearance streams must be regenerated. If you modify a field value, you + // should call setNeedAppearances(true) unless you also generate an appearance stream for the + // corresponding annotation at the same time. If you generate appearance streams for all fields, + // you can call setNeedAppearances(false). If you use QPDFFormFieldObjectHelper::setV, it will + // automatically call this method unless you tell it not to. + QPDF_DLL + void setNeedAppearances(bool); + + // If /NeedAppearances is false, do nothing. Otherwise generate appearance streams for all + // widget annotations that need them. See comments in QPDFFormFieldObjectHelper.hh for + // generateAppearance for limitations. For checkbox and radio button fields, this code ensures + // that appearance state is consistent with the field's value and uses any pre-existing + // appearance streams. + QPDF_DLL + void generateAppearancesIfNeeded(); + + // Disable Digital Signature Fields. Remove all digital signature fields from the document, + // leaving any annotation showing the content of the field intact. This also calls + // QPDF::removeSecurityRestrictions. + QPDF_DLL + void disableDigitalSignatures(); + + // Note: this method works on all annotations, not just ones with associated fields. For each + // annotation in old_annots, apply the given transformation matrix to create a new annotation. + // New annotations are appended to new_annots. If the annotation is associated with a form + // field, a new form field is created that points to the new annotation and is appended to + // new_fields, and the old field is added to old_fields. + // + // old_annots may belong to a different QPDF object. In that case, you should pass in from_qpdf, + // and copyForeignObject will be called automatically. If this is the case, for efficiency, you + // may pass in a QPDFAcroFormDocumentHelper for the other file to avoid the expensive process of + // creating one for each call to transformAnnotations. New fields and annotations are not added + // to the document or pages. You have to do that yourself after calling transformAnnotations. If + // this operation will leave orphaned fields behind, such as if you are replacing the old + // annotations with the new ones on the same page and the fields and annotations are not shared, + // you will also need to remove the old fields to prevent them from hanging around unreferenced. + QPDF_DLL + void transformAnnotations( + QPDFObjectHandle old_annots, + std::vector& new_annots, + std::vector& new_fields, + std::set& old_fields, + QPDFMatrix const& cm, + QPDF* from_qpdf = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + // Copy form fields and annotations from one page to another, allowing the from page to be in a + // different QPDF or in the same QPDF. This would typically be called after calling addPage to + // add field/annotation awareness. When just copying the page by itself, annotations end up + // being shared, and fields end up being omitted because there is no reference to the field from + // the page. This method ensures that each separate copy of a page has private annotations and + // that fields and annotations are properly updated to resolve conflicts that may occur from + // common resource and field names across documents. It is basically a wrapper around + // transformAnnotations that handles updating the receiving page. If new_fields is non-null, any + // newly created fields are added to it. + QPDF_DLL + void fixCopiedAnnotations( + QPDFObjectHandle to_page, + QPDFObjectHandle from_page, + QPDFAcroFormDocumentHelper& from_afdh, + std::set* new_fields = nullptr); + + private: + friend class QPDF::Doc; + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFACROFORMDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFAnnotationObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFAnnotationObjectHelper.hh new file mode 100644 index 0000000..1f50d80 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFAnnotationObjectHelper.hh @@ -0,0 +1,105 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFANNOTATIONOBJECTHELPER_HH +#define QPDFANNOTATIONOBJECTHELPER_HH + +#include +#include + +#include + +class QPDFAnnotationObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFAnnotationObjectHelper(QPDFObjectHandle); + + ~QPDFAnnotationObjectHelper() override = default; + + // This class provides helper methods for annotations. More functionality will likely be added + // in the future. + + // Some functionality for annotations is also implemented in QPDFAcroFormDocumentHelper and + // QPDFFormFieldObjectHelper. In some cases, functions defined there work for other annotations + // besides widget annotations, but they are implemented with form fields so that they can + // properly handle form fields when needed. + + // Return the subtype of the annotation as a string (e.g. "/Widget"). Returns an empty string + // if the subtype (which is required by the spec) is missing. + QPDF_DLL + std::string getSubtype(); + + QPDF_DLL + QPDFObjectHandle::Rectangle getRect(); + + QPDF_DLL + QPDFObjectHandle getAppearanceDictionary(); + + // Return the appearance state as given in "/AS", or an empty string if none is given. + QPDF_DLL + std::string getAppearanceState(); + + // Return flags from "/F". The value is a logical or of pdf_annotation_flag_e as defined in + // qpdf/Constants.h. + QPDF_DLL + int getFlags(); + + // Return a specific stream. "which" may be one of "/N", "/R", or "/D" to indicate the normal, + // rollover, or down appearance stream. (Any value may be passed to "which"; if an appearance + // stream of that name exists, it will be returned.) If the value associated with "which" in the + // appearance dictionary is a subdictionary, an appearance state may be specified to select + // which appearance stream is desired. If not specified, the appearance state in "/AS" will + // used. + QPDF_DLL + QPDFObjectHandle getAppearanceStream(std::string const& which, std::string const& state = ""); + + // Generate text suitable for addition to the containing page's content stream that draws this + // annotation's appearance stream as a form XObject. The value "name" is the resource name that + // will be used to refer to the form xobject. The value "rotate" should be set to the page's + // /Rotate value or 0 if none. The values of required_flags and forbidden_flags are constructed + // by logically "or"ing annotation flags of type pdf_annotation_flag_e defined in + // qpdf/Constants.h. Content will be returned only if all required_flags are set and no + // forbidden_flags are set. For example, including an_no_view in forbidden_flags could be useful + // for creating an on-screen view, and including an_print to required_flags could be useful if + // preparing to print. + QPDF_DLL + std::string getPageContentForAppearance( + std::string const& name, + int rotate, + int required_flags = 0, + int forbidden_flags = an_invisible | an_hidden); + + private: + class Members + { + friend class QPDFAnnotationObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFANNOTATIONOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFCryptoImpl.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFCryptoImpl.hh new file mode 100644 index 0000000..34bbd98 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFCryptoImpl.hh @@ -0,0 +1,82 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFCRYPTOIMPL_HH +#define QPDFCRYPTOIMPL_HH + +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. +// Most users won't need to know or care about this class, but you can +// use it if you want to supply your own crypto implementation. To do +// so, provide an implementation of QPDFCryptoImpl, ensure that you +// register it by calling QPDFCryptoProvider::registerImpl, and make +// it the default by calling QPDFCryptoProvider::setDefaultProvider. +class QPDF_DLL_CLASS QPDFCryptoImpl +{ + public: + QPDFCryptoImpl() = default; + + virtual ~QPDFCryptoImpl() = default; + + // Random Number Generation + + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + // Hashing + + typedef unsigned char MD5_Digest[16]; + virtual void MD5_init() = 0; + virtual void MD5_update(unsigned char const* data, size_t len) = 0; + virtual void MD5_finalize() = 0; + virtual void MD5_digest(MD5_Digest) = 0; + + virtual void SHA2_init(int bits) = 0; + virtual void SHA2_update(unsigned char const* data, size_t len) = 0; + virtual void SHA2_finalize() = 0; + virtual std::string SHA2_digest() = 0; + + // Encryption/Decryption + + // QPDF must support RC4 to be able to work with older PDF files + // and readers. Search for RC4 in README.md + + // key_len of -1 means treat key_data as a null-terminated string + virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0; + // out_data = 0 means to encrypt/decrypt in place + virtual void + RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data = nullptr) = 0; + virtual void RC4_finalize() = 0; + + static size_t constexpr rijndael_buf_size = 16; + virtual void rijndael_init( + bool encrypt, + unsigned char const* key_data, + size_t key_len, + bool cbc_mode, + unsigned char* cbc_block) = 0; + virtual void rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0; + virtual void rijndael_finalize() = 0; +}; + +#endif // QPDFCRYPTOIMPL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFCryptoProvider.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFCryptoProvider.hh new file mode 100644 index 0000000..44d900c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFCryptoProvider.hh @@ -0,0 +1,107 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFCRYPTOPROVIDER_HH +#define QPDFCRYPTOPROVIDER_HH + +#include +#include +#include +#include +#include +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. Most users won't need to know or +// care about this class, but you can use it if you want to supply your own crypto implementation. +// See also comments in QPDFCryptoImpl.hh. +class QPDFCryptoProvider +{ + public: + // Methods for getting and registering crypto implementations. These methods are not + // thread-safe. + + // Return an instance of a crypto provider using the default implementation. + QPDF_DLL + static std::shared_ptr getImpl(); + + // Return an instance of the crypto provider registered using the given name. + QPDF_DLL + static std::shared_ptr getImpl(std::string const& name); + + typedef std::function()> provider_fn; + + // Register a crypto implementation with the given name. The provider function must return + // a shared pointer to an instance of the implementation class, which must be derived from + // QPDFCryptoImpl. + QPDF_DLL static void registerImpl(std::string const& name, provider_fn f); + + // Register the given type (T) as a crypto implementation. T must be derived from QPDFCryptoImpl + // and must have a constructor that takes no arguments. + template + static void + registerImpl(std::string const& name) + { + registerImpl(name, std::make_shared); + } + + // Set the crypto provider registered with the given name as the default crypto implementation. + QPDF_DLL + static void setDefaultProvider(std::string const& name); + + // Get the names of registered implementations + QPDF_DLL + static std::set getRegisteredImpls(); + + // Get the name of the default crypto provider + QPDF_DLL + static std::string getDefaultProvider(); + + private: + QPDFCryptoProvider(); + ~QPDFCryptoProvider() = default; + QPDFCryptoProvider(QPDFCryptoProvider const&) = delete; + QPDFCryptoProvider& operator=(QPDFCryptoProvider const&) = delete; + + static QPDFCryptoProvider& getInstance(); + + std::shared_ptr getImpl_internal(std::string const& name) const; + void registerImpl_internal(std::string const& name, provider_fn f); + void setDefaultProvider_internal(std::string const& name); + + class Members + { + friend class QPDFCryptoProvider; + + public: + Members() = default; + ~Members() = default; + + private: + Members(Members const&) = delete; + Members& operator=(Members const&) = delete; + + std::string default_provider; + std::map providers; + }; + + std::shared_ptr m; +}; + +#endif // QPDFCRYPTOPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFDocumentHelper.hh new file mode 100644 index 0000000..67d42d4 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFDocumentHelper.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFDOCUMENTHELPER_HH +#define QPDFDOCUMENTHELPER_HH + +#include +#include + +// This is a base class for QPDF Document Helper classes. Document helpers are classes that provide +// a convenient, higher-level API for accessing document-level structures within a PDF file. +// Document helpers are always initialized with a reference to a QPDF object, and the object can +// always be retrieved. The intention is that you may freely intermix use of document helpers with +// the underlying QPDF object unless there is a specific comment in a specific helper method that +// says otherwise. The pattern of using helper objects was introduced to allow creation of higher +// level helper functions without polluting the public interface of QPDF. +class QPDF_DLL_CLASS QPDFDocumentHelper +{ + public: + QPDFDocumentHelper(QPDF& qpdf) : + qpdf(qpdf) + { + } + QPDF_DLL + virtual ~QPDFDocumentHelper(); + QPDF& + getQPDF() + { + return qpdf; + } + QPDF const& + getQPDF() const + { + return qpdf; + } + + protected: + QPDF& qpdf; +}; + +#endif // QPDFDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFEFStreamObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFEFStreamObjectHelper.hh new file mode 100644 index 0000000..fec2325 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFEFStreamObjectHelper.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEFSTREAMOBJECTHELPER_HH +#define QPDFEFSTREAMOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around Embedded File Streams, which are discussed in +// section 7.11.4 of the ISO-32000 PDF specification. +class QPDFEFStreamObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFEFStreamObjectHelper(QPDFObjectHandle); + + ~QPDFEFStreamObjectHelper() override = default; + + // Date parameters are strings that conform to the PDF spec for date/time strings, which is + // "D:yyyymmddhhmmss" where is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone + // offset. Examples: "D:20210207161528-05'00'", "D:20210207211528Z". See + // QUtil::qpdf_time_to_pdf_time. + + QPDF_DLL + std::string getCreationDate(); + QPDF_DLL + std::string getModDate(); + // Get size as reported in the object; return 0 if not present. + QPDF_DLL + size_t getSize(); + // Subtype is a mime type such as "text/plain" + QPDF_DLL + std::string getSubtype(); + // Return the checksum as stored in the object as a binary string. This does not check + // consistency with the data. If not present, return an empty string. The PDF spec specifies + // this as an MD5 checksum and notes that it is not to be used for security purposes since MD5 + // is known to be insecure. + QPDF_DLL + std::string getChecksum(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // efsoh.setCreationDate(x).setModDate(y); + + // Create a new embedded file stream with the given stream data, which can be provided in any of + // several ways. To get the new object back, call getObjectHandle() on the returned object. The + // checksum and size are computed automatically and stored. Other parameters may be supplied + // using setters defined below. + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::shared_ptr data); + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::string const& data); + // The provider function must write the data to the given pipeline. The function may be called + // multiple times by the qpdf library. You can pass QUtil::file_provider(filename) as the + // provider to have the qpdf library provide the contents of filename as a binary. + QPDF_DLL + static QPDFEFStreamObjectHelper + createEFStream(QPDF& qpdf, std::function provider); + + // Setters for other parameters + QPDF_DLL + QPDFEFStreamObjectHelper& setCreationDate(std::string const&); + QPDF_DLL + QPDFEFStreamObjectHelper& setModDate(std::string const&); + + // Set subtype as a mime-type, e.g. "text/plain" or "application/pdf". + QPDF_DLL + QPDFEFStreamObjectHelper& setSubtype(std::string const&); + + private: + QPDFObjectHandle getParam(std::string const& pkey); + void setParam(std::string const& pkey, QPDFObjectHandle const&); + static QPDFEFStreamObjectHelper newFromStream(QPDFObjectHandle stream); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEFSTREAMOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh new file mode 100644 index 0000000..12174d6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh @@ -0,0 +1,90 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEMBEDDEDFILEDOCUMENTHELPER_HH +#define QPDFEMBEDDEDFILEDOCUMENTHELPER_HH + +#include + +#include +#include +#include +#include + +#include +#include + +// This class provides a higher level interface around document-level file attachments, also known +// as embedded files. These are discussed in sections 7.7.4 and 7.11 of the ISO-32000 PDF +// specification. +class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the EmbeddedFiles structure, which can be expensive. + QPDF_DLL + static QPDFEmbeddedFileDocumentHelper& get(QPDF& qpdf); + + // Re-validate the EmbeddedFiles structure. This is useful if you have modified the structure of + // the EmbeddedFiles dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFEmbeddedFileDocumentHelper(QPDF&); + + ~QPDFEmbeddedFileDocumentHelper() override = default; + + QPDF_DLL + bool hasEmbeddedFiles() const; + + QPDF_DLL + std::map> getEmbeddedFiles(); + + // If an embedded file with the given name exists, return a (shared) pointer to it. Otherwise, + // return nullptr. + QPDF_DLL + std::shared_ptr getEmbeddedFile(std::string const& name); + + // Add or replace an attachment + QPDF_DLL + void replaceEmbeddedFile(std::string const& name, QPDFFileSpecObjectHelper const&); + + // Remove an embedded file if present. Return value is true if the file was present and was + // removed. This method not only removes the embedded file from the embedded files name tree but + // also nulls out the file specification dictionary. This means that any references to this file + // from file attachment annotations will also stop working. This is the best way to make the + // attachment actually disappear from the file and not just from the list of attachments. + QPDF_DLL + bool removeEmbeddedFile(std::string const& name); + + private: + void initEmbeddedFiles(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEMBEDDEDFILEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFExc.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFExc.hh new file mode 100644 index 0000000..9038418 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFExc.hh @@ -0,0 +1,89 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEXC_HH +#define QPDFEXC_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFExc: public std::runtime_error +{ + public: + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message, + bool zero_offset_valid); + + ~QPDFExc() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. Only the error code and message are + // guaranteed to have non-zero/empty values. + + // There is no lookup code that maps numeric error codes into strings. The numeric error code + // is just another way to get at the underlying issue, but it is more programmer-friendly than + // trying to parse a string that is subject to change. + + QPDF_DLL + qpdf_error_code_e getErrorCode() const; + QPDF_DLL + std::string const& getFilename() const; + QPDF_DLL + std::string const& getObject() const; + QPDF_DLL + qpdf_offset_t getFilePosition() const; + QPDF_DLL + std::string const& getMessageDetail() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat( + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + qpdf_error_code_e error_code; + std::string filename; + std::string object; + qpdf_offset_t offset; + std::string message; +}; + +#endif // QPDFEXC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFFileSpecObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFFileSpecObjectHelper.hh new file mode 100644 index 0000000..9a00e20 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFFileSpecObjectHelper.hh @@ -0,0 +1,94 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFILESPECOBJECTHELPER_HH +#define QPDFFILESPECOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around File Specification dictionaries, which are +// discussed in section 7.11 of the ISO-32000 PDF specification. +class QPDFFileSpecObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFileSpecObjectHelper(QPDFObjectHandle); + + ~QPDFFileSpecObjectHelper() override = default; + + QPDF_DLL + std::string getDescription(); + + // Get the main filename for this file specification. In priority order, check /UF, /F, /Unix, + // /DOS, /Mac. + QPDF_DLL + std::string getFilename(); + + // Return any of /UF, /F, /Unix, /DOS, /Mac filename keys that may be present in the object. + QPDF_DLL + std::map getFilenames(); + + // Get the requested embedded file stream for this file specification. If key is empty, In + // priority order, check /UF, /F, /Unix, /DOS, /Mac. Returns a null object if not found. If this + // is an actual embedded file stream, its data is the content of the attachment. You can also + // use QPDFEFStreamObjectHelper for higher level access to the parameters. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStream(std::string const& key = ""); + + // Return the /EF key of the file spec, which is a map from file name key to embedded file + // stream. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStreams(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // fsoh.setDescription(x).setFilename(y); + + // Create a new filespec as an indirect object with the given filename, and attach the contents + // of the specified file as data in an embedded file stream. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, std::string const& fullpath); + + // Create a new filespec as an indirect object with the given unicode filename and embedded file + // stream. The file name will be used as both /UF and /F. If you need to override, call + // setFilename. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper); + + QPDF_DLL + QPDFFileSpecObjectHelper& setDescription(std::string const&); + // setFilename sets /UF to unicode_name. If compat_name is empty, it is also set to + // unicode_name. unicode_name should be a UTF-8 encoded string. compat_name is converted to a + // string QPDFObjectHandle literally, preserving whatever encoding it might happen to have. + QPDF_DLL + QPDFFileSpecObjectHelper& + setFilename(std::string const& unicode_name, std::string const& compat_name = ""); + + private: + class Members; + std::shared_ptr m; +}; + +#endif // QPDFFILESPECOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFFormFieldObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFFormFieldObjectHelper.hh new file mode 100644 index 0000000..a929563 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFFormFieldObjectHelper.hh @@ -0,0 +1,195 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFORMFIELDOBJECTHELPER_HH +#define QPDFFORMFIELDOBJECTHELPER_HH + +#include + +#include +#include + +class QPDFAnnotationObjectHelper; + +// This object helper helps with form fields for interactive forms. Please see comments in +// QPDFAcroFormDocumentHelper.hh for additional details. +class QPDFFormFieldObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFormFieldObjectHelper(); + QPDF_DLL + QPDFFormFieldObjectHelper(QPDFObjectHandle); + + ~QPDFFormFieldObjectHelper() override = default; + + QPDF_DLL + bool isNull(); + + // Return the field's parent. A form field object helper whose underlying object is null is + // returned if there is no parent. This condition may be tested by calling isNull(). + QPDF_DLL + QPDFFormFieldObjectHelper getParent(); + + // Return the top-level field for this field. Typically this will be the field itself or its + // parent. If is_different is provided, it is set to true if the top-level field is different + // from the field itself; otherwise it is set to false. + QPDF_DLL + QPDFFormFieldObjectHelper getTopLevelField(bool* is_different = nullptr); + + // Get a field value, possibly inheriting the value from an ancestor node. + QPDF_DLL + QPDFObjectHandle getInheritableFieldValue(std::string const& name); + + // Get an inherited field value as a string. If it is not a string, silently return the empty + // string. + QPDF_DLL + std::string getInheritableFieldValueAsString(std::string const& name); + + // Get an inherited field value of type name as a string representing the name. If it is not a + // name, silently return the empty string. + QPDF_DLL + std::string getInheritableFieldValueAsName(std::string const& name); + + // Returns the value of /FT if present, otherwise returns the empty string. + QPDF_DLL + std::string getFieldType(); + + QPDF_DLL + std::string getFullyQualifiedName(); + + QPDF_DLL + std::string getPartialName(); + + // Return the alternative field name (/TU), which is the field name intended to be presented to + // users. If not present, fall back to the fully qualified name. + QPDF_DLL + std::string getAlternativeName(); + + // Return the mapping field name (/TM). If not present, fall back to the alternative name, then + // to the partial name. + QPDF_DLL + std::string getMappingName(); + + QPDF_DLL + QPDFObjectHandle getValue(); + + // Return the field's value as a string. If this is called with a field whose value is not a + // string, the empty string will be silently returned. + QPDF_DLL + std::string getValueAsString(); + + QPDF_DLL + QPDFObjectHandle getDefaultValue(); + + // Return the field's default value as a string. If this is called with a field whose value is + // not a string, the empty string will be silently returned. + QPDF_DLL + std::string getDefaultValueAsString(); + + // Return the default appearance string, taking inheritance from the field tree into account. + // Returns the empty string if the default appearance string is not available (because it's + // erroneously absent or because this is not a variable text field). If not found in the field + // hierarchy, look in /AcroForm. + QPDF_DLL + std::string getDefaultAppearance(); + + // Return the default resource dictionary for the field. This comes not from the field but from + // the document-level /AcroForm dictionary. While several PDF generators put a /DR key in the + // form field's dictionary, experimentation suggests that many popular readers, including Adobe + // Acrobat and Acrobat Reader, ignore any /DR item on the field. + QPDF_DLL + QPDFObjectHandle getDefaultResources(); + + // Return the quadding value, taking inheritance from the field tree into account. Returns 0 if + // quadding is not specified. Look in /AcroForm if not found in the field hierarchy. + QPDF_DLL + int getQuadding(); + + // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as defined in + // qpdf/Constants.h + QPDF_DLL + int getFlags(); + + // Methods for testing for particular types of form fields + + // Returns true if field is of type /Tx + QPDF_DLL + bool isText(); + // Returns true if field is of type /Btn and flags do not indicate some other type of button. + QPDF_DLL + bool isCheckbox(); + // Returns true if field is a checkbox and is checked. + QPDF_DLL + bool isChecked(); + // Returns true if field is of type /Btn and flags indicate that it is a radio button + QPDF_DLL + bool isRadioButton(); + // Returns true if field is of type /Btn and flags indicate that it is a pushbutton + QPDF_DLL + bool isPushbutton(); + // Returns true if field is of type /Ch + QPDF_DLL + bool isChoice(); + // Returns choices display values as UTF-8 strings + QPDF_DLL + std::vector getChoices(); + + // Set an attribute to the given value. If you have a QPDFAcroFormDocumentHelper and you want to + // set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, QPDFObjectHandle value); + + // Set an attribute to the given value as a Unicode string (UTF-16 BE encoded). The input string + // should be UTF-8 encoded. If you have a QPDFAcroFormDocumentHelper and you want to set the + // name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, std::string const& utf8_value); + + // Set /V (field value) to the given value. If need_appearances is true and the field type is + // either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this + // method not to set /NeedAppearances if you are going to generate an appearance stream + // yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes, + // radio buttons, pushbuttons) specially. When setting a checkbox value, any value other than + // /Off will be treated as on, and the actual value set will be based on the appearance stream's + // /N dictionary, so the value that ends up in /V may not exactly match the value you pass in. + QPDF_DLL + void setV(QPDFObjectHandle value, bool need_appearances = true); + + // Set /V (field value) to the given string value encoded as a Unicode string. The input value + // should be UTF-8 encoded. See comments above about /NeedAppearances. + QPDF_DLL + void setV(std::string const& utf8_value, bool need_appearances = true); + + // Update the appearance stream for this field. Note that qpdf's ability to generate appearance + // streams is limited. We only generate appearance streams for streams of type text or choice. + // The appearance uses the default parameters provided in the file, and it only supports ASCII + // characters. Quadding is currently ignored. While this functionality is limited, it should do + // a decent job on properly constructed PDF files when field values are restricted to ASCII + // characters. + QPDF_DLL + void generateAppearance(QPDFAnnotationObjectHelper&); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFFORMFIELDOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFJob.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFJob.hh new file mode 100644 index 0000000..cace443 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFJob.hh @@ -0,0 +1,542 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFJOB_HH +#define QPDFJOB_HH + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFWriter; +class Pipeline; +class QPDFLogger; + +class QPDFJob +{ + public: + static int constexpr LATEST_JOB_JSON = 1; + + // Exit codes -- returned by getExitCode() after calling run() + static int constexpr EXIT_ERROR = qpdf_exit_error; + static int constexpr EXIT_WARNING = qpdf_exit_warning; + // For is-encrypted and requires-password + static int constexpr EXIT_IS_NOT_ENCRYPTED = qpdf_exit_is_not_encrypted; + static int constexpr EXIT_CORRECT_PASSWORD = qpdf_exit_correct_password; + + // QPDFUsage is thrown if there are any usage-like errors when calling Config methods. + QPDF_DLL + QPDFJob(); + + // SETUP FUNCTIONS + + // Initialize a QPDFJob object from argv, which must be a null-terminated array of + // null-terminated UTF-8-encoded C strings. The progname_env argument is the name of an + // environment variable which, if set, overrides the name of the executable for purposes of + // generating the --completion options. See QPDFArgParser for details. If a null pointer is + // passed in, the default value of "QPDF_EXECUTABLE" is used. This is used by the QPDF cli, + // which just initializes a QPDFJob from argv, calls run(), and handles errors and exit status + // issues. You can perform much of the cli functionality programmatically in this way rather + // than using the regular API. This is exposed in the C API, which makes it easier to get + // certain high-level qpdf functionality from other languages. If there are any command-line + // errors, this method will throw QPDFUsage which is derived from std::runtime_error. Other + // exceptions may be thrown in some cases. Note that argc, and argv should be UTF-8 encoded. If + // you are calling this from a Windows Unicode-aware main (wmain), see + // QUtil::call_main_from_wmain for information about converting arguments to UTF-8. This method + // will mutate arguments that are passed to it. + QPDF_DLL + void initializeFromArgv(char const* const argv[], char const* progname_env = nullptr); + + // Initialize a QPDFJob from json. Passing partial = true prevents this method from doing the + // final checks (calling checkConfiguration) after processing the json file. This makes it + // possible to initialize QPDFJob in stages using multiple json files or to have a json file + // that can be processed from the CLI with --job-json-file and be combined with other arguments. + // For example, you might include only encryption parameters, leaving it up to the rest of the + // command-line arguments to provide input and output files. initializeFromJson is called with + // partial = true when invoked from the command line. To make sure that the json file is fully + // valid on its own, just don't specify any other command-line flags. If there are any + // configuration errors, QPDFUsage is thrown. Some error messages may be CLI-centric. If an + // exception tells you to use the "--some-option" option, set the "someOption" key in the JSON + // object instead. + QPDF_DLL + void initializeFromJson(std::string const& json, bool partial = false); + + // Set name that is used to prefix verbose messages, progress messages, and other things that + // the library writes to output and error streams on the caller's behalf. Defaults to "qpdf". + QPDF_DLL + void setMessagePrefix(std::string const&); + QPDF_DLL + std::string getMessagePrefix() const; + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // If you set a custom logger here, the logger will be passed to all subsequent QPDF objects + // created by this QPDFJob object. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // You can register a custom progress reporter to be called by QPDFWriter (see + // QPDFWriter::registerProgressReporter). This is only called if you also request progress + // reporting through normal configuration methods (e.g., pass --progress, call + // config()->progress, etc.) + QPDF_DLL + void registerProgressReporter(std::function); + + // Check to make sure no contradictory options have been specified. This is called automatically + // after initializing from argv or json and is also called by run, but you can call it manually + // as well. It throws a QPDFUsage exception if there are any errors. This Config object (see + // CONFIGURATION) also has a checkConfiguration method which calls this one. + QPDF_DLL + void checkConfiguration(); + + // Returns true if output is created by the specified job. + QPDF_DLL + bool createsOutput() const; + + // SEE BELOW FOR MORE PUBLIC METHODS AND CLASSES + private: + // These structures are private but we need to define them before the public Config classes. + struct CopyAttachmentFrom + { + std::string path; + std::string password; + std::string prefix; + }; + + struct AddAttachment + { + std::string path; + std::string key; + std::string filename; + std::string creationdate; + std::string moddate; + std::string mimetype; + std::string description; + bool replace{false}; + }; + + public: + // CONFIGURATION + + // Configuration classes are implemented in QPDFJob_config.cc. + + // The config() method returns a shared pointer to a Config object. The Config object contains + // methods that correspond with qpdf command-line arguments. You can use a fluent interface to + // configure a QPDFJob object that would do exactly the same thing as a specific qpdf command. + // The example qpdf-job.cc contains an example of this usage. You can also use + // initializeFromJson or initializeFromArgv to initialize a QPDFJob object. + + // Notes about the Config methods: + // + // * Most of the method declarations are automatically generated in header files that are + // included within the class definitions. They correspond in predictable ways to the + // command-line arguments and are generated from the same code that generates the command-line + // argument parsing code. + // + // * Methods return pointers, rather than references, to configuration objects. References + // might feel more familiar to users of fluent interfaces, so why do we use pointers? The + // main methods that create them return smart pointers so that users can initialize them when + // needed, which you can't do with references. Returning pointers instead of references makes + // for a more uniform interface. + + // Maintainer documentation: see the section in README-maintainer called "HOW TO ADD A + // COMMAND-LINE ARGUMENT", which contains references to additional places in the documentation. + + class Config; + + class AttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endAddAttachment(); + QPDF_DLL + AttConfig* file(std::string const& parameter); + +#include + + private: + AttConfig(Config*); + AttConfig(AttConfig const&) = delete; + + Config* config; + AddAttachment att; + }; + + class CopyAttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endCopyAttachmentsFrom(); + QPDF_DLL + CopyAttConfig* file(std::string const& parameter); + +#include + + private: + CopyAttConfig(Config*); + CopyAttConfig(CopyAttConfig const&) = delete; + + Config* config; + CopyAttachmentFrom caf; + }; + + class PagesConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endPages(); + // From qpdf 11.9.0, you can call file(), range(), and password(). Each call to file() + // starts a new page spec. + QPDF_DLL + PagesConfig* pageSpec( + std::string const& filename, std::string const& range, char const* password = nullptr); + +#include + + private: + PagesConfig(Config*); + PagesConfig(PagesConfig const&) = delete; + + Config* config; + }; + + class UOConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endUnderlayOverlay(); + +#include + + private: + UOConfig(Config*); + UOConfig(UOConfig const&) = delete; + + Config* config; + }; + + class EncConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endEncrypt(); + QPDF_DLL + EncConfig* file(std::string const& parameter); + +#include + + private: + EncConfig(Config*); + EncConfig(EncConfig const&) = delete; + + Config* config; + }; + + class PageLabelsConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endSetPageLabels(); + +#include + + private: + PageLabelsConfig(Config*); + PageLabelsConfig(PageLabelsConfig const&) = delete; + + Config* config; + }; + + class GlobalConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endGlobal(); + +#include + + GlobalConfig(Config*); // for qpdf internal use only + GlobalConfig(GlobalConfig const&) = delete; + + private: + Config* config; + }; + + class Config + { + friend class QPDFJob; + + public: + // Proxy to QPDFJob::checkConfiguration() + QPDF_DLL + void checkConfiguration(); + + QPDF_DLL + Config* inputFile(std::string const& filename); + QPDF_DLL + Config* emptyInput(); + QPDF_DLL + Config* outputFile(std::string const& filename); + QPDF_DLL + Config* replaceInput(); + QPDF_DLL + Config* setPageLabels(std::vector const& specs); + + QPDF_DLL + std::shared_ptr copyAttachmentsFrom(); + QPDF_DLL + std::shared_ptr addAttachment(); + QPDF_DLL + std::shared_ptr global(); + QPDF_DLL + std::shared_ptr pages(); + QPDF_DLL + std::shared_ptr overlay(); + QPDF_DLL + std::shared_ptr underlay(); + QPDF_DLL + std::shared_ptr + encrypt(int keylen, std::string const& user_password, std::string const& owner_password); + +#include + + private: + Config() = delete; + Config(Config const&) = delete; + Config(QPDFJob& job) : + o(job) + { + } + QPDFJob& o; + }; + + // Return a top-level configuration item. See CONFIGURATION above for details. If an invalid + // configuration is created (such as supplying contradictory options, omitting an input file, + // etc.), QPDFUsage is thrown. Note that error messages are CLI-centric, but you can map them + // into config calls. For example, if an exception tells you to use the --some-option flag, you + // should call config()->someOption() instead. + QPDF_DLL + std::shared_ptr config(); + + // Execute the job + QPDF_DLL + void run(); + + // The following two methods allow a job to be run in two stages - creation of a QPDF object and + // writing of the QPDF object. This allows the QPDF object to be modified prior to writing it + // out. See examples/qpdfjob-remove-annotations for an illustration of its use. + + // Run the first stage of the job. Return a nullptr if the configuration is not valid. + QPDF_DLL + std::unique_ptr createQPDF(); + + // Run the second stage of the job. Do nothing if a nullptr is passed as parameter. + QPDF_DLL + void writeQPDF(QPDF& qpdf); + + // CHECK STATUS -- these methods provide information known after run() is called. + + QPDF_DLL + bool hasWarnings() const; + + // Return one of the EXIT_* constants defined at the top of the class declaration. This may be + // called after run() when run() did not throw an exception. Takes into consideration whether + // isEncrypted or requiresPassword was called. Note that this function does not know whether + // run() threw an exception, so code that uses this to determine how to exit should explicitly + // use EXIT_ERROR if run() threw an exception. + QPDF_DLL + int getExitCode() const; + + // Return value is bitwise OR of values from qpdf_encryption_status_e + QPDF_DLL + unsigned long getEncryptionStatus(); + + // HELPER FUNCTIONS -- methods useful for calling in handlers that interact with QPDFJob during + // run or initialization. + + // If in verbose mode, call the given function, passing in the output stream and message prefix. + QPDF_DLL + void doIfVerbose(std::function fn); + + // Provide a string that is the help information ("schema" for the qpdf-specific JSON object) + // for the specified version of JSON output. + QPDF_DLL + static std::string json_out_schema(int version); + + [[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL json_out_schema_v1(); + + // Provide a string that is the help information for specified version of JSON format for + // QPDFJob. + QPDF_DLL + static std::string job_json_schema(int version); + + [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1(); + + private: + struct PageNo; + struct Selection; + struct Input; + struct Inputs; + struct RotationSpec; + struct UnderOverlay; + struct PageLabelSpec; + + enum password_mode_e { pm_bytes, pm_hex_bytes, pm_unicode, pm_auto }; + + // Helper functions + static void usage(std::string const& msg); + static JSON json_schema(int json_version, std::set* keys = nullptr); + static void parse_object_id(std::string const& objspec, bool& trailer, int& obj, int& gen); + void parseRotationParameter(std::string const&); + std::vector parseNumrange(char const* range, int max); + + // Basic file processing + void processFile( + std::unique_ptr&, + char const* filename, + char const* password, + bool used_for_input, + bool main_input); + void processInputSource( + std::unique_ptr&, + std::shared_ptr is, + char const* password, + bool used_for_input); + void doProcess( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + void doProcessOnce( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + + // Transformations + void handlePageSpecs(QPDF& pdf); + bool shouldRemoveUnreferencedResources(QPDF& pdf); + void handleRotations(QPDF& pdf); + void getUOPagenos( + std::vector& uo, std::vector>>& pagenos); + void handleUnderOverlay(QPDF& pdf); + std::string doUnderOverlayForPage( + QPDF& pdf, + UnderOverlay& uo, + std::vector>>& pagenos, + PageNo const& page_idx, + size_t uo_idx, + std::map>& fo, + QPDFPageObjectHelper& dest_page); + void validateUnderOverlay(QPDF& pdf, UnderOverlay* uo); + void handleTransformations(QPDF& pdf); + void addAttachments(QPDF& pdf); + void copyAttachments(QPDF& pdf); + + // Inspection + void doInspection(QPDF& pdf); + void doCheck(QPDF& pdf); + void showEncryption(QPDF& pdf); + void doShowObj(QPDF& pdf); + void doShowPages(QPDF& pdf); + void doListAttachments(QPDF& pdf); + void doShowAttachment(QPDF& pdf); + + // Output generation + void doSplitPages(QPDF& pdf); + void setWriterOptions(qpdf::Writer&); + void setEncryptionOptions(QPDFWriter&); + void maybeFixWritePassword(int R, std::string& password); + void writeOutfile(QPDF& pdf); + void writeJSON(QPDF& pdf); + + // JSON + void doJSON(QPDF& pdf, Pipeline*); + QPDFObjGen::set getWantedJSONObjects(); + void doJSONObjects(Pipeline* p, bool& first, QPDF& pdf); + void doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPages(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPageLabels(Pipeline* p, bool& first, QPDF& pdf); + void doJSONOutlines(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAcroform(Pipeline* p, bool& first, QPDF& pdf); + void doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf); + void addOutlinesToJson( + std::vector outlines, + JSON& j, + std::map& page_numbers); + + enum remove_unref_e { re_auto, re_yes, re_no }; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOBJECT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFLogger.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFLogger.hh new file mode 100644 index 0000000..1e360be --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFLogger.hh @@ -0,0 +1,164 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFLOGGER_HH +#define QPDFLOGGER_HH + +#include +#include +#include +#include + +class QPDFLogger +{ + public: + QPDF_DLL + static std::shared_ptr create(); + + // Return the default logger. In general, you should use the default logger. You can also create + // your own loggers and use them with QPDF and QPDFJob objects, but there are few reasons to do + // so. One reason may be that you are using multiple QPDF or QPDFJob objects in different + // threads and want to capture output and errors to different streams. (Note that a single QPDF + // or QPDFJob can't be safely used from multiple threads, but it is safe to use separate QPDF + // and QPDFJob objects on separate threads.) Another possible reason would be if you are writing + // an application that uses the qpdf library directly and qpdf is also used by a downstream + // library or if you are using qpdf from a library and don't want to interfere with potential + // uses of qpdf by other libraries or applications. + QPDF_DLL + static std::shared_ptr defaultLogger(); + + // Defaults: + // + // info -- if save is standard output, standard error, else standard output + // warn -- whatever error points to + // error -- standard error + // save -- undefined unless set + // + // "info" is used for diagnostic messages, verbose messages, and progress messages. "warn" is + // used for warnings. "error" is used for errors. "save" is used for saving output -- see below. + // + // On deletion, finish() is called for the standard output and standard error pipelines, which + // flushes output. If you supply any custom pipelines, you must call finish() on them yourself. + // Note that calling finish is not needed for string, stdio, or ostream pipelines. + // + // NOTES ABOUT THE SAVE PIPELINE + // + // The save pipeline is used by QPDFJob when some kind of binary output is being saved. This + // includes saving attachments and stream data and also includes when the output file is + // standard output. If you want to grab that output, you can call setSave. See + // examples/qpdfjob-save-attachment.cc and examples/qpdfjob-c-save-attachment.c. + // + // You should never set the save pipeline to the same destination as something else. Doing so + // will corrupt your save output. If you want to save to standard output, use the method + // saveToStandardOutput(). In addition to setting the save pipeline, that does the following + // extra things: + // + // * If standard output has been used, a logic error is thrown + // * If info is set to standard output at the time of the set save call, it is switched to + // standard error. + // + // This is not a guarantee. You can still mess this up in ways that are not checked. Here are a + // few examples: + // + // * Don't set any pipeline to standard output *after* passing it to setSave() + // * Don't use a separate mechanism to write stdout/stderr other than + // QPDFLogger::standardOutput() + // * Don't set anything to the same custom pipeline that save is set to. + // + // Just be sure that if you change pipelines around, you should avoid having the save pipeline + // also be used for any other purpose. The special case for saving to standard output allows you + // to call saveToStandardOutput() early without having to worry about the info pipeline. + + QPDF_DLL + void info(char const*); + QPDF_DLL + void info(std::string const&); + QPDF_DLL + std::shared_ptr getInfo(bool null_okay = false); + + QPDF_DLL + void warn(char const*); + QPDF_DLL + void warn(std::string const&); + QPDF_DLL + std::shared_ptr getWarn(bool null_okay = false); + + QPDF_DLL + void error(char const*); + QPDF_DLL + void error(std::string const&); + QPDF_DLL + std::shared_ptr getError(bool null_okay = false); + + QPDF_DLL + std::shared_ptr getSave(bool null_okay = false); + + QPDF_DLL + std::shared_ptr standardOutput(); + QPDF_DLL + std::shared_ptr standardError(); + QPDF_DLL + std::shared_ptr discard(); + + // Passing a null pointer resets to default + QPDF_DLL + void setInfo(std::shared_ptr); + QPDF_DLL + void setWarn(std::shared_ptr); + QPDF_DLL + void setError(std::shared_ptr); + // See notes above about the save pipeline + QPDF_DLL + void setSave(std::shared_ptr, bool only_if_not_set); + QPDF_DLL + void saveToStandardOutput(bool only_if_not_set); + + // Shortcut for logic to reset output to new output/error streams. out_stream is used for info, + // err_stream is used for error, and warning is cleared so that it follows error. + QPDF_DLL + void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + private: + QPDFLogger(); + std::shared_ptr throwIfNull(std::shared_ptr, bool null_okay); + + class Members + { + friend class QPDFLogger; + + public: + ~Members(); + + private: + Members(); + Members(Members const&) = delete; + + std::shared_ptr p_discard; + std::shared_ptr p_real_stdout; + std::shared_ptr p_stdout; + std::shared_ptr p_stderr; + std::shared_ptr p_info; + std::shared_ptr p_warn; + std::shared_ptr p_error; + std::shared_ptr p_save; + }; + std::shared_ptr m; +}; + +#endif // QPDFLOGGER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFMatrix.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFMatrix.hh new file mode 100644 index 0000000..37624df --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFMatrix.hh @@ -0,0 +1,93 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFMATRIX_HH +#define QPDFMATRIX_HH + +#include +#include +#include + +// This class represents a PDF transformation matrix using a tuple such that +// +// ┌ ┐ +// │ a b 0 │ +// (a, b, c, d, e, f) = │ c d 0 │ +// │ e f 1 │ +// └ ┘ +class QPDFMatrix +{ + public: + QPDF_DLL + QPDFMatrix(); + QPDF_DLL + QPDFMatrix(double a, double b, double c, double d, double e, double f); + QPDF_DLL + QPDFMatrix(QPDFObjectHandle::Matrix const&); + + // Returns the six values separated by spaces as real numbers with trimmed zeroes. + QPDF_DLL + std::string unparse() const; + + QPDF_DLL + QPDFObjectHandle::Matrix getAsMatrix() const; + + // Replace this with other * this + QPDF_DLL + void concat(QPDFMatrix const& other); + + // Same as concat(sx, 0, 0, sy, 0, 0) + QPDF_DLL + void scale(double sx, double sy); + + // Same as concat(1, 0, 0, 1, tx, ty); + QPDF_DLL + void translate(double tx, double ty); + + // Any value other than 90, 180, or 270 is ignored + QPDF_DLL + void rotatex90(int angle); + + // Transform a point. The underlying operation is to take + // [x y 1] * this + // and take the first and second rows of the result as xp and yp. + QPDF_DLL + void transform(double x, double y, double& xp, double& yp) const; + + // Transform a rectangle by creating a new rectangle that tightly bounds the polygon resulting + // from transforming the four corners. + QPDF_DLL + QPDFObjectHandle::Rectangle transformRectangle(QPDFObjectHandle::Rectangle r) const; + + // operator== tests for exact equality, not considering deltas for floating point. + QPDF_DLL + bool operator==(QPDFMatrix const& rhs) const; + + QPDF_DLL + bool operator!=(QPDFMatrix const& rhs) const; + + double a; + double b; + double c; + double d; + double e; + double f; +}; + +#endif // QPDFMATRIX_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFNameTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFNameTreeObjectHelper.hh new file mode 100644 index 0000000..7677819 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFNameTreeObjectHelper.hh @@ -0,0 +1,184 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNAMETREEOBJECTHELPER_HH +#define QPDFNAMETREEOBJECTHELPER_HH + +#include +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for name trees. See section 7.9.6 in the PDF spec (ISO 32000) for a +// description of name trees. When looking up items in the name tree, use UTF-8 strings. All names +// are normalized for lookup purposes. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNameTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNameTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Create an empty name tree + QPDF_DLL + static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + QPDF_DLL + ~QPDFNameTreeObjectHelper() override; + + // Return whether the name tree has an explicit entry for this name. + QPDF_DLL + bool hasName(std::string const& utf8); + + // Find an object by name. If found, returns true and initializes oh. See also find(). + QPDF_DLL + bool findObject(std::string const& utf8, QPDFObjectHandle& oh); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNameTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(std::string const& key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a string and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(std::string const& key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(std::string const& key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(std::string const& key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the name tree as a map. Note that name trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNameTreeObjectHelper's iterator. + QPDF_DLL + std::map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNAMETREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFNumberTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFNumberTreeObjectHelper.hh new file mode 100644 index 0000000..b7d7716 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFNumberTreeObjectHelper.hh @@ -0,0 +1,200 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNUMBERTREEOBJECTHELPER_HH +#define QPDFNUMBERTREEOBJECTHELPER_HH + +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for number trees. See section 7.9.7 in the PDF spec (ISO 32000) for a +// description of number trees. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNumberTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNumberTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + QPDF_DLL + ~QPDFNumberTreeObjectHelper() override; + + // Create an empty number tree + QPDF_DLL + static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + typedef long long int numtree_number; + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Return overall minimum and maximum indices + QPDF_DLL + numtree_number getMin(); + QPDF_DLL + numtree_number getMax(); + + // Return whether the number tree has an explicit entry for this number. + QPDF_DLL + bool hasIndex(numtree_number idx); + + // Find an object with a specific index. If found, returns true and initializes oh. See also + // find(). + QPDF_DLL + bool findObject(numtree_number idx, QPDFObjectHandle& oh); + // Find the object at the index or, if not found, the object whose index is the highest index + // less than the requested index. If the requested index is less than the minimum, return false. + // Otherwise, return true, initialize oh to the object, and set offset to the difference between + // the requested index and the actual index. For example, if a number tree has values for 3 and + // 6 and idx is 5, this method would return true, initialize oh to the value with index 3, and + // set offset to 2 (5 - 3). See also find(). + QPDF_DLL + bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNumberTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(numtree_number key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a numtree_number and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(numtree_number key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(numtree_number key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(numtree_number key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the number tree as a map. Note that number trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNumberTreeObjectHelper's iterator. + typedef std::map idx_map; + QPDF_DLL + idx_map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNUMBERTREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjGen.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjGen.hh new file mode 100644 index 0000000..1f92488 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjGen.hh @@ -0,0 +1,137 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJGEN_HH +#define QPDFOBJGEN_HH + +#include + +#include +#include +#include + +class QPDFObjectHandle; +class QPDFObjectHelper; + +// This class represents an object ID and generation pair. It is suitable to use as a key in a map +// or set. + +class QPDFObjGen +{ + public: + QPDFObjGen() = default; + QPDFObjGen(int obj, int gen) : + obj(obj), + gen(gen) + { + } + bool + operator<(QPDFObjGen const& rhs) const + { + return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen); + } + bool + operator==(QPDFObjGen const& rhs) const + { + return obj == rhs.obj && gen == rhs.gen; + } + bool + operator!=(QPDFObjGen const& rhs) const + { + return !(*this == rhs); + } + int + getObj() const + { + return obj; + } + int + getGen() const + { + return gen; + } + bool + isIndirect() const + { + return obj != 0; + } + std::string + unparse(char separator = ',') const + { + return std::to_string(obj) + separator + std::to_string(gen); + } + friend std::ostream& + operator<<(std::ostream& os, QPDFObjGen og) + { + os << og.obj << "," << og.gen; + return os; + } + + // Convenience class for loop detection when processing objects. + // + // The class adds 'add' methods to a std::set which allows to test whether an + // QPDFObjGen is present in the set and to insert it in a single operation. The 'add' method is + // overloaded to take a QPDFObjGen, QPDFObjectHandle or an QPDFObjectHelper as parameter. + // + // The erase method is modified to ignore requests to erase QPDFObjGen(0, 0). + // + // Usage example: + // + // void process_object(QPDFObjectHandle oh, QPDFObjGen::set& seen) + // { + // if (seen.add(oh)) { + // // handle first encounter of oh + // } else { + // // handle loop / subsequent encounter of oh + // } + // } + class QPDF_DLL_CLASS set: public std::set + { + public: + // Add 'og' to the set. Return false if 'og' is already present in the set. Attempts to + // insert QPDFObjGen(0, 0) are ignored. + bool + add(QPDFObjGen og) + { + if (og.isIndirect()) { + if (count(og)) { + return false; + } + emplace(og); + } + return true; + } + + void + erase(QPDFObjGen og) + { + if (og.isIndirect()) { + std::set::erase(og); + } + } + }; + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created and destroyed. + int obj{0}; + int gen{0}; +}; + +#endif // QPDFOBJGEN_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObject.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObject.hh new file mode 100644 index 0000000..8499637 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObject.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECT_OLD_HH +#define QPDFOBJECT_OLD_HH + +// Current code should not include . This file exists +// to ensure that code that includes it doesn't accidentally work because +// of an old qpdf installed on the system. Including this file became an +// error with qpdf version 12. The internal QPDFObject API is defined in +// QPDFObject_private.hh, which is not part of the public API. + +// Instead of including this header, include , and +// replace `QPDFObject::ot_` with `::ot_` in your code. +#error "QPDFObject.hh is obsolete; see comments in QPDFObject.hh for details" + +#endif // QPDFOBJECT_OLD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjectHandle.hh new file mode 100644 index 0000000..9fef4e6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjectHandle.hh @@ -0,0 +1,1576 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECTHANDLE_HH +#define QPDFOBJECTHANDLE_HH + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class Pipeline; +class QPDF_Array; +class QPDF_Bool; +class QPDF_Dictionary; +class QPDF_InlineImage; +class QPDF_Integer; +class QPDF_Name; +class QPDF_Null; +class QPDF_Operator; +class QPDF_Real; +class QPDF_Reserved; +class QPDF_Stream; +class QPDF_String; +class QPDFObject; +class QPDFObjectHandle; +class QPDFTokenizer; +class QPDFExc; +class Pl_QPDFTokenizer; +class QPDFMatrix; +namespace qpdf::impl +{ + class Parser; +} + +class QPDFObjectHandle: public qpdf::BaseHandle +{ + friend class qpdf::impl::Parser; + + public: + // This class is used by replaceStreamData. It provides an alternative way of associating + // stream data with a stream. See comments on replaceStreamData and newStream for additional + // details. + class QPDF_DLL_CLASS StreamDataProvider + { + public: + QPDF_DLL + StreamDataProvider(bool supports_retry = false); + + QPDF_DLL + virtual ~StreamDataProvider(); + // The implementation of this function must write stream data to the given pipeline. The + // stream data must conform to whatever filters are explicitly associated with the stream. + // QPDFWriter may, in some cases, add compression, but if it does, it will update the + // filters as needed. Every call to provideStreamData for a given stream must write the same + // data. Note that, when writing linearized files, qpdf will call your provideStreamData + // twice, and if it generates different output, you risk generating invalid output or having + // qpdf throw an exception. The object ID and generation passed to this method are those + // that belong to the stream on behalf of which the provider is called. They may be ignored + // or used by the implementation for indexing or other purposes. This information is made + // available just to make it more convenient to use a single StreamDataProvider object to + // provide data for multiple streams. + + // A few things to keep in mind: + // + // * Stream data providers must not modify any objects since they may be called after some + // parts of the file have already been written. + // + // * Since qpdf may call provideStreamData multiple times when writing linearized files, if + // the work done by your stream data provider is slow or computationally intensive, you + // might want to implement your own cache. + // + // * Once you have called replaceStreamData, the original stream data is no longer directly + // accessible from the stream, but this is easy to work around by copying the stream to + // a separate QPDF object. The qpdf library implements this very efficiently without + // actually making a copy of the stream data. You can find examples of this pattern in + // some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc. + + // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or + // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by + // allowing an alternative provideStreamData to be implemented. You must implement at least + // one of the versions of provideStreamData below. If you implement the version that + // supports retry and returns a value, you should pass true as the value of supports_retry + // in the base class constructor. This will cause the library to call that version of the + // method, which should also return a boolean indicating whether it ran without errors. + QPDF_DLL + virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline); + QPDF_DLL + virtual bool provideStreamData( + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline); + QPDF_DLL virtual bool provideStreamData( + int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL + bool supportsRetry(); + + private: + bool supports_retry; + }; + + // The TokenFilter class provides a way to filter content streams in a lexically aware fashion. + // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter + // methods or can be applied on the spot by filterPageContents. You may also use + // Pl_QPDFTokenizer directly if you need full control. + // + // The handleToken method is called for each token, including the eof token, and then handleEOF + // is called at the very end. Handlers may call write (or writeToken) to pass data downstream. + // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of + // using TokenFilters. + // + // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you + // get the canonical, "parsed" representation of the token. For a string, this means that there + // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits) + // has been resolved. qpdf's internal representation of a name includes the leading slash. As + // such, you can't write the value of token.getValue() directly to output that is supposed to be + // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can + // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new + // string or name token from a canonical representation, use + // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or + // QPDFTokenizer::Token(QPDFTokenizer::tt_name, + // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can + // still write them with writeToken(). Example: + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain")) + // would write `/text#2fplain`, and + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`. + class QPDF_DLL_CLASS TokenFilter + { + public: + TokenFilter() = default; + virtual ~TokenFilter() = default; + virtual void handleToken(QPDFTokenizer::Token const&) = 0; + QPDF_DLL + virtual void handleEOF(); + + class PipelineAccessor + { + friend class Pl_QPDFTokenizer; + + private: + static void + setPipeline(TokenFilter* f, Pipeline* p) + { + f->setPipeline(p); + } + }; + + protected: + QPDF_DLL + void write(char const* data, size_t len); + QPDF_DLL + void write(std::string const& str); + QPDF_DLL + void writeToken(QPDFTokenizer::Token const&); + + private: + QPDF_DLL_PRIVATE + void setPipeline(Pipeline*); + + Pipeline* pipeline; + }; + + // This class is used by parse to decrypt strings when reading an object that contains encrypted + // strings. + class StringDecrypter + { + public: + virtual ~StringDecrypter() = default; + virtual void decryptString(std::string& val) = 0; + }; + + // This class is used by parsePageContents. Callers must instantiate a subclass of this with + // handlers defined to accept QPDFObjectHandles that are parsed from the stream. + class QPDF_DLL_CLASS ParserCallbacks + { + public: + virtual ~ParserCallbacks() = default; + // One of the handleObject methods must be overridden. + QPDF_DLL + virtual void handleObject(QPDFObjectHandle); + QPDF_DLL + virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length); + + virtual void handleEOF() = 0; + + // Override this if you want to know the full size of the contents, possibly after + // concatenation of multiple streams. This is called before the first call to handleObject. + QPDF_DLL + virtual void contentSize(size_t); + + protected: + // Implementors may call this method during parsing to terminate parsing early. This method + // throws an exception that is caught by parsePageContents, so its effect is immediate. + QPDF_DLL + void terminateParsing(); + }; + + // Convenience object for rectangles + class Rectangle + { + public: + Rectangle() : + llx(0.0), + lly(0.0), + urx(0.0), + ury(0.0) + { + } + Rectangle(double llx, double lly, double urx, double ury) : + llx(llx), + lly(lly), + urx(urx), + ury(ury) + { + } + + double llx; + double lly; + double urx; + double ury; + }; + + // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't + // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity + // transform matrix and this one is all zeroes. + class Matrix + { + public: + Matrix() : + a(0.0), + b(0.0), + c(0.0), + d(0.0), + e(0.0), + f(0.0) + { + } + Matrix(double a, double b, double c, double d, double e, double f) : + a(a), + b(b), + c(c), + d(d), + e(e), + f(f) + { + } + + double a; + double b; + double c; + double d; + double e; + double f; + }; + + QPDFObjectHandle() = default; + QPDFObjectHandle(QPDFObjectHandle const&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default; + QPDFObjectHandle(QPDFObjectHandle&&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default; + + // This method is provided for backward compatibility only. New code should convert to bool + // instead. + inline bool isInitialized() const; + + // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying + // object, meaning that changes to one are reflected in the other, or "if you paint one, the + // other one changes color." This does not perform a structural comparison of the contents of + // the objects. + QPDF_DLL + bool isSameObjectAs(QPDFObjectHandle const&) const; + + // Return type code and type name of underlying object. These are useful for doing rapid type + // tests (like switch statements) or for testing and debugging. + QPDF_DLL + qpdf_object_type_e getTypeCode() const; + QPDF_DLL + char const* getTypeName() const; + + // Exactly one of these will return true for any initialized object. Operator and InlineImage + // are only allowed in content streams. + QPDF_DLL + bool isBool() const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + bool isInteger() const; + QPDF_DLL + bool isReal() const; + QPDF_DLL + bool isName() const; + QPDF_DLL + bool isString() const; + QPDF_DLL + bool isOperator() const; + QPDF_DLL + bool isInlineImage() const; + QPDF_DLL + bool isArray() const; + QPDF_DLL + bool isDictionary() const; + QPDF_DLL + bool isStream() const; + QPDF_DLL + bool isReserved() const; + + // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended + // for internal use, but it can be used as an efficient way to check for nulls that are not + // indirect objects. + QPDF_DLL + bool isDirectNull() const; + + // This returns true in addition to the query for the specific type for indirect objects. + QPDF_DLL + bool isIndirect() const; + + // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse + // such an object will throw a logic_error. + QPDF_DLL + bool isDestroyed() const; + + // True for everything except array, dictionary, stream, word, and inline image. + QPDF_DLL + bool isScalar() const; + + // True if the object is a name object representing the provided name. + QPDF_DLL + bool isNameAndEquals(std::string const& name) const; + + // True if the object is a dictionary of the specified type and subtype, if any. + QPDF_DLL + bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const; + + // True if the object is a stream of the specified type and subtype, if any. + QPDF_DLL + bool isStreamOfType(std::string const& type, std::string const& subtype = "") const; + + // Public factory methods + + // Wrap an object in an array if it is not already an array. This is a helper for cases in which + // something in a PDF may either be a single item or an array of items, which is a common idiom. + QPDF_DLL + QPDFObjectHandle wrapInArray(); + + // Construct an object of any type from a string representation of the object. Throws QPDFExc + // with an empty filename and an offset into the string if there is an error. Any indirect + // object syntax (obj gen R) will cause a logic_error exception to be thrown. If + // object_description is provided, it will appear in the message of any QPDFExc exception thrown + // for invalid syntax. See also the global `operator ""_qpdf` defined below. + QPDF_DLL + static QPDFObjectHandle + parse(std::string const& object_str, std::string const& object_description = ""); + + // Construct an object of any type from a string representation of the object. Indirect object + // syntax (obj gen R) is allowed and will create indirect references within the passed-in + // context. If object_description is provided, it will appear in the message of any QPDFExc + // exception thrown for invalid syntax. Note that you can't parse an indirect object reference + // all by itself as parse will stop at the end of the first complete object, which will just be + // the first number and will report that there is trailing data at the end of the string. + QPDF_DLL + static QPDFObjectHandle + parse(QPDF* context, std::string const& object_str, std::string const& object_description = ""); + + // Construct an object as above by reading from the given InputSource at its current position + // and using the tokenizer you supply. Indirect objects and encrypted strings are permitted. + // This method was intended to be called by QPDF for parsing objects that are read from the + // object's input stream. To be removed in qpdf 13. See + // . + [[deprecated("to be removed in qpdf 13")]] QPDF_DLL static QPDFObjectHandle parse( + std::shared_ptr input, + std::string const& object_description, + QPDFTokenizer&, + bool& empty, + StringDecrypter* decrypter, + QPDF* context); + + // Return the offset where the object was found when parsed. A negative value means that the + // object was created without parsing. If the object is in a stream, the offset is from the + // beginning of the stream. Otherwise, the offset is from the beginning of the file. + QPDF_DLL + qpdf_offset_t getParsedOffset() const; + + // Older method: stream_or_array should be the value of /Contents from a page object. It's more + // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error + // messages will also be more useful because the page object information will be known. + QPDF_DLL + static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks); + + // When called on a stream or stream array that is some page's content streams, do the same as + // pipePageContents. This method is a lower level way to do what + // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a + // contents object that is disconnected from a page object. The description argument should + // describe the containing page and is used in error messages. The all_description argument is + // initialized to something that could be used to describe the result of the pipeline. It is the + // description amended with the identifiers of the underlying objects. Please note that if there + // is an array of content streams, p->finish() is called after each stream. If you pass a + // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an + // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the + // end. + QPDF_DLL + void + pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description); + + // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream + // data is passed through the token filter after all original filters but before content stream + // normalization if requested. This is a low-level interface to add it to a stream. You will + // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be + // applied to a page object, and which will automatically handle the case of pages whose + // contents are split across multiple streams. + QPDF_DLL + void addTokenFilter(std::shared_ptr token_filter); + + // Legacy helpers for parsing content streams. These methods are not going away, but newer code + // should call the correspond methods in QPDFPageObjectHelper instead. The specification and + // behavior of these methods are the same as the identically named methods in that class, but + // newer functionality will be added there. + QPDF_DLL + void parsePageContents(ParserCallbacks* callbacks); + QPDF_DLL + void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr); + // See comments for QPDFPageObjectHelper::pipeContents. + QPDF_DLL + void pipePageContents(Pipeline* p); + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + // End legacy content stream helpers + + // Called on a stream to filter the stream as if it were page contents. This can be used to + // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream. + QPDF_DLL + void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr); + // Called on a stream to parse the stream as page contents. This can be used to parse a form + // XObject. + QPDF_DLL + void parseAsContents(ParserCallbacks* callbacks); + + // Type-specific factories + QPDF_DLL + static QPDFObjectHandle newNull(); + QPDF_DLL + static QPDFObjectHandle newBool(bool value); + QPDF_DLL + static QPDFObjectHandle newInteger(long long value); + QPDF_DLL + static QPDFObjectHandle newReal(std::string const& value); + QPDF_DLL + static QPDFObjectHandle + newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true); + // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes, + // excluding the NUL character, and starting with a slash. Name objects as represented in the + // PDF specification can contain characters escaped with #, but such escaping is not of concern + // when calling QPDFObjectHandle methods not directly relating to parsing. For example, + // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return + // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse() + // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and + // modifying objects, you want to work with the internal, canonical representation. For names + // containing alphanumeric characters, dashes, and underscores, there is no difference between + // the two representations. For a lengthy discussion, see + // https://github.com/qpdf/qpdf/discussions/625. + QPDF_DLL + static QPDFObjectHandle newName(std::string const& name); + QPDF_DLL + static QPDFObjectHandle newString(std::string const& str); + // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in + // PDF files outside of content streams, such as in document metadata form field values, page + // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16 + // as needed to successfully encode all the characters. + QPDF_DLL + static QPDFObjectHandle newUnicodeString(std::string const& utf8_str); + QPDF_DLL + static QPDFObjectHandle newOperator(std::string const&); + QPDF_DLL + static QPDFObjectHandle newInlineImage(std::string const&); + QPDF_DLL + static QPDFObjectHandle newArray(); + QPDF_DLL + static QPDFObjectHandle newArray(std::vector const& items); + QPDF_DLL + static QPDFObjectHandle newArray(Rectangle const&); + QPDF_DLL + static QPDFObjectHandle newArray(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newArray(QPDFMatrix const&); + QPDF_DLL + static QPDFObjectHandle newDictionary(); + QPDF_DLL + static QPDFObjectHandle newDictionary(std::map const& items); + + // Create an array from a rectangle. Equivalent to the rectangle form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromRectangle(Rectangle const&); + // Create an array from a matrix. Equivalent to the matrix form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromMatrix(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newFromMatrix(QPDFMatrix const&); + + // Note: new stream creation methods have were added to the QPDF class starting with + // version 11.2.0. The ones in this class are here for backward compatibility. + + // Create a new stream and associate it with the given qpdf object. A subsequent call must be + // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be + // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively, + // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can + // call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf); + + // Create a new stream and associate it with the given qpdf object. Use the given buffer as the + // stream data. The stream dictionary's /Length key will automatically be set to the size of the + // data buffer. If additional keys are required, the stream's dictionary may be retrieved by + // calling getDict(), and the resulting dictionary may be modified. This method is just a + // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience + // methods for streams that require no parameters beyond the stream length. Note that you don't + // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will + // automatically compress uncompressed stream data. Example programs are provided that + // illustrate this. From QPDF 11.2, you can call QPDF::newStream() + // instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + // From QPDF 11.2, you can call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call + // QPDF::newReserved() instead. + QPDF_DLL + static QPDFObjectHandle newReserved(QPDF* qpdf); + + // Provide an owning qpdf and object description. The library does this automatically with + // objects that are read from the input PDF and with objects that are created programmatically + // and inserted into the QPDF as a new indirect object. Most end user code will not need to call + // this. If an object has an owning qpdf and object description, it enables qpdf to give + // warnings with proper context in some cases where it would otherwise raise exceptions. It is + // okay to add objects without an owning_qpdf to objects that have one, but it is an error to + // have a QPDF contain objects with owning_qpdf set to something else. To add objects from + // another qpdf, use copyForeignObject instead. + QPDF_DLL + void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description); + QPDF_DLL + bool hasObjectDescription() const; + + // Accessor methods + // + // (Note: this comment is referenced in qpdf-c.h and the manual.) + // + // In PDF files, objects have specific types, but there is nothing that prevents PDF files from + // containing objects of types that aren't expected by the specification. + // + // There are two flavors of accessor methods: + // + // * getSomethingValue() returns the value and issues a type warning if the type is incorrect. + // + // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns + // true and initializes a reference of the appropriate type. These methods never issue type + // warnings. + // + // The getSomethingValue() accessors and some of the other methods expect objects of a + // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as + // trying to get a dictionary key from an array, trying to get the string value of a number, + // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using + // the following behavior: + // + // * Requesting a value of the wrong type (int value from string, array item from a scalar or + // dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for + // number, the empty string for string, or the null object for an object handle. + // + // * Accessing an array item that is out of bounds will return a null object. + // + // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to + // a scalar or array) will be ignored. + // + // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5, + // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code + // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case + // for all objects whose origin was a PDF file), the warning is issued using the normal warning + // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them. + // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created + // programmatically), an exception will be thrown. + // + // The way to avoid getting any type warnings or exceptions, even when working with malformed + // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for + // example, make sure that isString() returns true before calling getStringValue()) and to + // always be sure that any array indices are in bounds. + // + // For additional discussion and rationale for this behavior, see the section in the QPDF manual + // entitled "Object Accessor Methods". + + // Methods for bool objects + QPDF_DLL + bool getBoolValue() const; + QPDF_DLL + bool getValueAsBool(bool&) const; + + // Methods for integer objects. Note: if an integer value is too big (too far away from zero in + // either direction) to fit in the requested return type, the maximum or minimum value for that + // return type may be returned. For example, on a system with 32-bit int, a numeric object with + // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX. + QPDF_DLL + long long getIntValue() const; + QPDF_DLL + bool getValueAsInt(long long&) const; + QPDF_DLL + int getIntValueAsInt() const; + QPDF_DLL + bool getValueAsInt(int&) const; + QPDF_DLL + unsigned long long getUIntValue() const; + QPDF_DLL + bool getValueAsUInt(unsigned long long&) const; + QPDF_DLL + unsigned int getUIntValueAsUInt() const; + QPDF_DLL + bool getValueAsUInt(unsigned int&) const; + + // Methods for real objects + QPDF_DLL + std::string getRealValue() const; + QPDF_DLL + bool getValueAsReal(std::string&) const; + + // Methods that work for both integer and real objects + QPDF_DLL + bool isNumber() const; + QPDF_DLL + double getNumericValue() const; + QPDF_DLL + bool getValueAsNumber(double&) const; + + // Methods for name objects. The returned name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + std::string getName() const; + QPDF_DLL + bool getValueAsName(std::string&) const; + + // Methods for string objects + QPDF_DLL + std::string getStringValue() const; + QPDF_DLL + bool getValueAsString(std::string&) const; + + // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise, + // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to + // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters + // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range + // unmapped. + QPDF_DLL + std::string getUTF8Value() const; + QPDF_DLL + bool getValueAsUTF8(std::string&) const; + + // Methods for content stream objects + QPDF_DLL + std::string getOperatorValue() const; + QPDF_DLL + bool getValueAsOperator(std::string&) const; + QPDF_DLL + std::string getInlineImageValue() const; + QPDF_DLL + bool getValueAsInlineImage(std::string&) const; + + // Methods for array objects; see also name and array objects. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.aitems()) + // { + // // iter is an array element + // } + class QPDFArrayItems; + QPDF_DLL + QPDFArrayItems aitems(); + + QPDF_DLL + int getArrayNItems() const; + QPDF_DLL + QPDFObjectHandle getArrayItem(int n) const; + // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling + // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of + // nulls. + QPDF_DLL + std::vector getArrayAsVector() const; + QPDF_DLL + bool isRectangle() const; + // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the + // rectangle [0, 0, 0, 0] + QPDF_DLL + Rectangle getArrayAsRectangle() const; + QPDF_DLL + bool isMatrix() const; + // If the array is an array of six numeric values, return as a matrix. Otherwise, return the + // matrix [1, 0, 0, 1, 0, 0] + QPDF_DLL + Matrix getArrayAsMatrix() const; + + // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as + // canonical name strings starting with a leading slash and not containing any PDF syntax + // escaping. See comments for getName() for details. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.ditems()) + // { + // // iter.first is the key + // // iter.second is the value + // } + class QPDFDictItems; + QPDF_DLL + QPDFDictItems ditems(); + + // Return true if key is present. Keys with null values are treated as if they are not present. + // This is as per the PDF spec. + QPDF_DLL + bool hasKey(std::string const&) const; + // Return the value for the key. If the key is not present, null is returned. + QPDF_DLL + QPDFObjectHandle getKey(std::string const&) const; + // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access + // lower-level dictionaries, as in + // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font"); + QPDF_DLL + QPDFObjectHandle getKeyIfDict(std::string const&) const; + // Return all keys. Keys with null values are treated as if they are not present. This is as + // per the PDF spec. + QPDF_DLL + std::set getKeys() const; + // Return dictionary as a map. Entries with null values are included. + QPDF_DLL + std::map getDictAsMap() const; + + // Methods for name and array objects. The name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + bool isOrHasName(std::string const&) const; + + // Make all resources in a resource dictionary indirect. This just goes through all entries of + // top-level subdictionaries and converts any direct objects to indirect objects. This can be + // useful to call before mergeResources if it is going to be called multiple times to prevent + // resources from being copied multiple times. + QPDF_DLL + void makeResourcesIndirect(QPDF& owning_qpdf); + + // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in + // dictionary subitems are resolved, and "conflicts" is initialized to a map such that + // conflicts[resource_type][old_key] == [new_key] + // + // See also makeResourcesIndirect, which can be useful to call before calling this. + // + // This method does nothing if both this object and the other object are not dictionaries. + // Otherwise, it has following behavior, where "object" refers to the object whose method is + // invoked, and "other" refers to the argument: + // + // * For each key in "other" whose value is an array: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, if "object" has an array in the same place, append to that array any objects + // in "other"'s array that are not already present. + // * For each key in "other" whose value is a dictionary: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, for each key in the subdictionary: + // * If key is not present in "object"'s entry, shallow copy it if direct or just add it if + // indirect. + // * Otherwise, if conflicts are being detected: + // * If there is a key (oldkey) already in the dictionary that points to the same indirect + // destination as key, indicate that key was replaced by oldkey. This would happen if + // these two resource dictionaries have previously been merged. + // * Otherwise pick a new key (newkey) that is unique within the resource dictionary, + // store that in the resource dictionary with key's destination as its destination, and + // indicate that key was replaced by newkey. + // + // The primary purpose of this method is to facilitate merging of resource dictionaries that are + // supposed to have the same scope as each other. For example, this can be used to merge a form + // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The + // "conflicts" parameter may be previously initialized. This method adds to whatever is already + // there, which can be useful when merging with multiple things. + QPDF_DLL + void mergeResources( + QPDFObjectHandle other, + std::map>* conflicts = nullptr); + + // Get all resource names from a resource dictionary. If this object is a dictionary, this + // method returns a set of all the keys in all top-level subdictionaries. For resources + // dictionaries, this is the collection of names that may be referenced in the content stream. + QPDF_DLL + std::set getResourceNames() const; + + // Find a unique name within a resource dictionary starting with a given prefix. This method + // works by appending a number to the given prefix. It searches starting with min_suffix and + // sets min_suffix to selected value upon return. This can be used to increase efficiency if + // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next + // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling + // this multiple times on the same resource dictionary, you can initialize resource_names by + // calling getResourceNames(), incrementally update it as you add resources, and keep passing it + // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time + // it's called. + QPDF_DLL + std::string getUniqueResourceName( + std::string const& prefix, + int& min_suffix, + std::set* resource_names = nullptr) const; + + // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF + // object. Indirect objects always have an owning QPDF. Direct objects that are read from the + // input source will also have an owning QPDF. Programmatically created objects will only have + // one if setObjectDescription was called. + // + // When the QPDF object that owns an object is destroyed, the object is changed into a null, and + // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the + // life of the QPDF. If in doubt, ask for it each time you need it. + + // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it + // returns a null pointer. Use this when you are able to handle the case of an object that + // doesn't have an owning QPDF. + QPDF_DLL + QPDF* getOwningQPDF() const; + // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a + // runtime_error. Use this when you know the object has to have an owning QPDF, such as when + // it's a known indirect object. Since streams are always indirect objects, this method can be + // used safely for streams. If error_msg is specified, it will be used at the contents of the + // runtime_error if there is now owner. + QPDF_DLL + QPDF& getQPDF(std::string const& error_msg = "") const; + + // Create a shallow copy of an object as a direct object, but do not traverse across indirect + // object boundaries. That means that, for dictionaries and arrays, any keys or items that were + // indirect objects will still be indirect objects that point to the same place. In the + // strictest sense, this is not a shallow copy because it recursively descends arrays and + // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You + // can't copy a stream this way. See copyStream() instead. + QPDF_DLL + QPDFObjectHandle shallowCopy(); + + // Create a true shallow copy of an array or dictionary, just copying the immediate items + // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in + // the copy, you are modifying the original, which is almost never what you want. However, if + // your intention is merely to *replace* top-level items or keys and not to modify lower-level + // items in the copy, this method is much faster than shallowCopy(). + QPDF_DLL + QPDFObjectHandle unsafeShallowCopy(); + + // Create a copy of this stream. The new stream and the old stream are independent: after the + // copy, either the original or the copy's dictionary or data can be modified without affecting + // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's + // data are made. If the source stream's data is already being provided by a StreamDataProvider, + // the new stream will use the same one, so you have to make sure your StreamDataProvider can + // handle that case. But if you're already using a StreamDataProvider, you probably don't need + // to call this method. + QPDF_DLL + QPDFObjectHandle copyStream(); + + // Mutator methods. + + // Since qpdf 11: for mutators that may add or remove an item, there are additional versions + // whose names contain "AndGet" that return the added or removed item. For example: + // + // auto new_dict = dict.replaceKeyAndGetNew( + // "/New", QPDFObjectHandle::newDictionary()); + // + // auto old_value = dict.replaceKeyAndGetOld( + // "/New", "(something)"_qpdf); + + // Recursively copy this object, making it direct. An exception is thrown if a loop is detected. + // With allow_streams true, keep indirect object references to streams. Otherwise, throw an + // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream + // is found, the resulting object is still associated with the containing qpdf. When + // allow_streams is false, the object will no longer be connected to the original QPDF object + // after this call completes successfully. + QPDF_DLL + void makeDirect(bool allow_streams = false); + + // Mutator methods for array objects + QPDF_DLL + void setArrayItem(int, QPDFObjectHandle const&); + QPDF_DLL + void setArrayFromVector(std::vector const& items); + // Insert an item before the item at the given position ("at") so that it has that position + // after insertion. If "at" is equal to the size of the array, insert the item at the end. + QPDF_DLL + void insertItem(int at, QPDFObjectHandle const& item); + // Like insertItem but return the item that was inserted. + QPDF_DLL + QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item); + // Append an item to an array. + QPDF_DLL + void appendItem(QPDFObjectHandle const& item); + // Append an item, and return the newly added item. + QPDF_DLL + QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item); + // Remove the item at that position, reducing the size of the array by one. + QPDF_DLL + void eraseItem(int at); + // Erase and item and return the item that was removed. + QPDF_DLL + QPDFObjectHandle eraseItemAndGetOld(int at); + + // Mutator methods for dictionary objects + + // Replace value of key, adding it if it does not exist. If value is null, remove the key. + QPDF_DLL + void replaceKey(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the value. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the old value, or null if the key was previously not present. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value); + // Remove key, doing nothing if key does not exist. + QPDF_DLL + void removeKey(std::string const& key); + // Remove key and return the old value. If the old value didn't exist, return a null object. + QPDF_DLL + QPDFObjectHandle removeKeyAndGetOld(std::string const& key); + + // Methods for stream objects + QPDF_DLL + QPDFObjectHandle getDict() const; + + // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode + // level, whether compression is enabled, and its ability to filter. Passing false will prevent + // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding + // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and + // recompressing a stream that it knows how to operate on for any application-specific reason, + // such as that you have already optimized its filtering. Note that this doesn't affect any + // other ways to get the stream's data, such as pipeStreamData or getStreamData. + QPDF_DLL + void setFilterOnWrite(bool); + QPDF_DLL + bool getFilterOnWrite(); + + // If addTokenFilter has been called for this stream, then the original data should be + // considered to be modified. This means we should avoid optimizations such as not filtering a + // stream that is already compressed. + QPDF_DLL + bool isDataModified(); + + // Returns filtered (uncompressed) stream data. Throws an exception if the stream is filtered + // and we can't decode it. + QPDF_DLL + std::shared_ptr getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized); + + // Returns unfiltered (raw) stream data. + QPDF_DLL + std::shared_ptr getRawStreamData(); + + // Write stream data through the given pipeline. A null pipeline value may be used if all you + // want to do is determine whether a stream is filterable and would be filtered based on the + // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags + // alter the behavior in the following way: + // + // encode_flags: + // + // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are + // applied. + // + // qpdf_sf_normalize -- tokenize as content stream and normalize tokens + // + // decode_level: + // + // qpdf_dl_none -- do not decode any streams. + // + // qpdf_dl_generalized -- decode supported general-purpose filters. This includes + // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode. + // + // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy + // specialized filters. This includes /RunLengthDecode. + // + // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported + // lossy filters. This includes /DCTDecode. + // + // If, based on the flags and the filters and decode parameters, we determine that we know how + // to apply all requested filters, do so and return true if we are successful. + // + // The exact meaning of the return value differs the different versions of this function, but + // for any version, the meaning has been the same. For the main version, added in qpdf 10, the + // return value indicates whether the overall operation succeeded. The filter parameter, if + // specified, will be set to whether or not filtering was attempted. If filtering was not + // requested, this value will be false even if the overall operation succeeded. + // + // If filtering is requested but this method returns false, it means there was some error in the + // filtering, in which case the resulting data is likely partially filtered and/or incomplete + // and may not be consistent with the configured filters. QPDFWriter handles this by attempting + // to get the stream data without filtering, but callers should consider a false return value + // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry + // in that case, pass true as the value of will_retry. This changes the warning issued by the + // library to indicate that the operation will be retried without filtering to avoid data loss. + + // Return value is overall success, even if filtering is not requested. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + bool* filtering_attempted, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy version. Return value is whether filtering was attempted. There is no way to determine + // success if filtering was not attempted. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows: + // filter = false -> encode_flags = 0 + // filter = true -> decode_level = qpdf_dl_generalized + // normalize = true -> encode_flags |= qpdf_sf_normalize + // compress = true -> encode_flags |= qpdf_sf_compress + // Return value is whether filtering was attempted. + QPDF_DLL + bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress); + + // Replace a stream's dictionary. The new dictionary must be consistent with the stream's data. + // This is most appropriately used when creating streams from scratch that will use a stream + // data provider and therefore start with an empty dictionary. It may be more convenient in + // this case than calling getDict and modifying it for each key. The pdf-create example does + // this. + QPDF_DLL + void replaceDict(QPDFObjectHandle const&); + + // Test whether a stream is the root XMP /Metadata object of its owning QPDF. + QPDF_DLL + bool isRootMetadata() const; + + // REPLACING STREAM DATA + + // Note about all replaceStreamData methods: whatever values are passed as filter and + // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object + // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf + // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing + // values untouched. + + // Replace this stream's stream data with the given data buffer. The stream's /Length key is + // replaced with the length of the data buffer. The stream is interpreted as if the data read + // from the file, after any decryption filters have been applied, is as presented. + QPDF_DLL + void replaceStreamData( + std::shared_ptr data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Replace the stream's stream data with the given string. This method will create a copy of the + // data rather than using the user-provided buffer as in the std::shared_ptr version of + // replaceStreamData. + QPDF_DLL + void replaceStreamData( + std::string const& data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // As above, replace this stream's stream data. Instead of directly providing a buffer with the + // stream data, call the given provider's provideStreamData method. See comments on the + // StreamDataProvider class (defined above) for details on the method. The data must be + // consistent with filter and decode_parms as provided. Although it is more complex to use this + // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid + // allocating memory for the stream data. Example programs are provided that use both forms of + // replaceStreamData. + + // Note about stream length: for any given stream, the provider must provide the same amount of + // data each time it is called. This is critical for making linearization work properly. + // Versions of qpdf before 3.0.0 required a length to be specified here. Starting with + // version 3.0.0, this is no longer necessary (or permitted). The first time the stream data + // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is + // enforced that the length be the same as the first time. + + // If you have gotten a compile error here while building code that worked with older versions + // of qpdf, just omit the length parameter. You can also simplify your code by not having to + // compute the length in advance. + QPDF_DLL + void replaceStreamData( + std::shared_ptr provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider. + + // The provider should write the stream data to the pipeline. For a one-liner to replace stream + // data with the contents of a file, pass QUtil::file_provider(filename) as provider. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + // The provider should write the stream data to the pipeline, returning true if it succeeded + // without errors. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Access object ID and generation. For direct objects, return object ID 0. + + // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to + // the pattern of depending on object ID or generation without the other. In general, when + // keeping track of object IDs, it's better to use QPDFObjGen instead. + + QPDF_DLL + QPDFObjGen getObjGen() const; + QPDF_DLL + int getObjectID() const; + QPDF_DLL + int getGeneration() const; + + QPDF_DLL + std::string unparse() const; + QPDF_DLL + std::string unparseResolved() const; + // For strings only, force binary representation. Otherwise, same as unparse. + QPDF_DLL + std::string unparseBinary() const; + + // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available + // JSON version. The JSON is generated as follows: + // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their + // native JSON types. + // * Names are encoded as strings representing the canonical representation (after parsing #xx) + // and preceded by a slash, just as unparse() returns. For example, the JSON for the + // PDF-syntax name /Text#2fPlain would be "/Text/Plain". + // * Indirect references are encoded as strings containing "obj gen R" + // * Strings + // * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters + // encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode + // mappings are not reversible. There is no way to tell the difference between a string that + // looks like a name or indirect object from an actual name or indirect object. + // * JSON v2: + // * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally + // mapped to Unicode (which is all strings without undefined characters) are represented + // as "u:" followed by the UTF-8 encoded string. Example: + // "u:potato". + // * All other strings are represented as "b:" followed by a hexadecimal encoding of the + // string. Example: "b:0102cacb" + // * Streams + // * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a + // dictionary other than context. + // * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the + // stream's dictionary. Since "dict" does not otherwise represent anything, this is + // unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data. + // * Object types that are only valid in content streams (inline image, operator) are serialized + // as "null". Attempting to serialize a "reserved" object is an error. + // If dereference_indirect is true and this is an indirect object, show the actual contents of + // the object. The effect of dereference_indirect applies only to this object. It is not + // recursive. + QPDF_DLL + JSON getJSON(int json_version, bool dereference_indirect = false) const; + + // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient + // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the + // documentation for getJSON and JSON::write for further detail. + QPDF_DLL + void writeJSON( + int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const; + + // This method can be called on a stream to get a more extended JSON representation of the + // stream that includes the stream's data. The JSON object returned is always a dictionary whose + // "dict" key is an encoding of the stream's dictionary. The representation of the data is + // determined by the json_data field. + // + // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file. + // + // If json_data is qpdf_sj_none, stream data is not represented. + // + // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on + // the value of decode_level, which has the same meaning as with pipeStreamData. + // + // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data" + // field of the dictionary that is returned. + // + // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be + // supplied. The value of data_filename is stored in the resulting json in the "datafile" key + // but is not otherwise use. The stream data itself (raw or filtered depending on decode level), + // is written to the pipeline via pipeStreamData(). + // + // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must + // remain valid until after the JSON object is written. + QPDF_DLL + JSON getStreamJSON( + int json_version, + qpdf_json_stream_data_e json_data, + qpdf_stream_decode_level_e decode_level, + Pipeline* p, + std::string const& data_filename); + + // Legacy helper methods for commonly performed operations on pages. Newer code should use + // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as + // the identically named methods in that class, but newer functionality will be added there. + QPDF_DLL + std::map getPageImages(); + QPDF_DLL + std::vector getPageContents(); + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + QPDF_DLL + void rotatePage(int angle, bool relative); + QPDF_DLL + void coalesceContentStreams(); + // End legacy page helpers + + // Issue a warning about this object if possible. If the object has a description, a warning + // will be issued using the owning QPDF as context. Otherwise, a message will be written to the + // default logger's error stream, which is standard error if not overridden. Objects read + // normally from the file have descriptions. See comments on setObjectDescription for additional + // details. + QPDF_DLL + void warnIfPossible(std::string const& warning) const; + + // Convenience routine: Throws if the assumption is violated. Your code will be better if you + // call one of the isType methods and handle the case of the type being wrong, but these can be + // convenient if you have already verified the type. + QPDF_DLL + void assertInitialized() const; + + QPDF_DLL + void assertNull() const; + QPDF_DLL + void assertBool() const; + QPDF_DLL + void assertInteger() const; + QPDF_DLL + void assertReal() const; + QPDF_DLL + void assertName() const; + QPDF_DLL + void assertString() const; + QPDF_DLL + void assertOperator() const; + QPDF_DLL + void assertInlineImage() const; + QPDF_DLL + void assertArray() const; + QPDF_DLL + void assertDictionary() const; + QPDF_DLL + void assertStream() const; + QPDF_DLL + void assertReserved() const; + + QPDF_DLL + void assertIndirect() const; + QPDF_DLL + void assertScalar() const; + QPDF_DLL + void assertNumber() const; + + // The isPageObject method checks the /Type key of the object. This is not completely reliable + // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is + // slightly more accepting but may still return false here when treating the object as a page + // would work. Use this sparingly. + QPDF_DLL + bool isPageObject() const; + QPDF_DLL + bool isPagesObject() const; + QPDF_DLL + void assertPageObject() const; + + QPDF_DLL + bool isFormXObject() const; + + // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as + // images. + QPDF_DLL + bool isImage(bool exclude_imagemask = true) const; + + // The following methods do not form part of the public API and are for internal use only. + + QPDFObjectHandle(std::shared_ptr const& obj) : + qpdf::BaseHandle(obj) + { + } + QPDFObjectHandle(std::shared_ptr&& obj) : + qpdf::BaseHandle(std::move(obj)) + { + } + std::shared_ptr + getObj() + { + return obj; + } + + void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const; + + inline qpdf::Array as_array(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Dictionary as_dictionary(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const; + + private: + void typeWarning(char const* expected_type, std::string const& warning) const; + void objectWarning(std::string const& warning) const; + void assertType(char const* type_name, bool istype) const; + void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); + void setParsedOffset(qpdf_offset_t offset); + void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); + static void parseContentStream_data( + std::string_view stream_data, + std::string const& description, + ParserCallbacks* callbacks, + QPDF* context); + std::vector + arrayOrStreamToStreamArray(std::string const& description, std::string& all_description); + void checkOwnership(QPDFObjectHandle const&) const; +}; + +#ifndef QPDF_NO_QPDF_STRING +// This is short for QPDFObjectHandle::parse, so you can do + +// auto oh = "<< /Key (value) >>"_qpdf; + +// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration +// from being here. + +/* clang-format off */ + // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest + // of the file as a string if clang-format removes the space after "operator", and as of + // clang-format 15, there's no way to prevent it from doing so. + QPDF_DLL + QPDFObjectHandle operator ""_qpdf(char const* v, size_t len); +/* clang-format on */ + +#endif // QPDF_NO_QPDF_STRING + +class QPDFObjectHandle::QPDFDictItems +{ + // This class allows C++-style iteration, including range-for iteration, around dictionaries. + // You can write + + // for (auto iter: QPDFDictItems(dictionary_obj)) + // { + // // iter.first is a string + // // iter.second is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFDictItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFDictItems; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFDictItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + std::set keys; + std::set::iterator iter; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +class QPDFObjectHandle::QPDFArrayItems +{ + // This class allows C++-style iteration, including range-for iteration, around arrays. You can + // write + + // for (auto iter: QPDFArrayItems(array_obj)) + // { + // // iter is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFArrayItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFArrayItems; + + public: + typedef QPDFObjectHandle T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFArrayItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + int item_number; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +namespace qpdf +{ + inline BaseHandle:: + operator bool() const + { + return static_cast(obj); + } + + inline BaseHandle:: + operator QPDFObjectHandle() const + { + return {obj}; + } + +} // namespace qpdf + +inline bool +QPDFObjectHandle::isInitialized() const +{ + return obj != nullptr; +} + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjectHelper.hh new file mode 100644 index 0000000..d19ba3b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFObjectHelper.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJECTHELPER_HH +#define QPDFOBJECTHELPER_HH + +#include + +#include + +// This is a base class for QPDF Object Helper classes. Object helpers are classes that provide a +// convenient, higher-level API for working with specific types of QPDF objects. Object helpers are +// always initialized with a QPDFObjectHandle, and the underlying object handle can always be +// retrieved. The intention is that you may freely intermix use of object helpers with the +// underlying QPDF objects unless there is a specific comment in a specific helper method that says +// otherwise. The pattern of using helper objects was introduced to allow creation of higher level +// helper functions without polluting the public interface of QPDFObjectHandle. +class QPDF_DLL_CLASS QPDFObjectHelper: public qpdf::BaseHandle +{ + public: + QPDFObjectHelper(QPDFObjectHandle oh) : + qpdf::BaseHandle(oh.getObj()) + { + } + QPDF_DLL + virtual ~QPDFObjectHelper(); + QPDFObjectHandle + getObjectHandle() + { + return {obj}; + } + QPDFObjectHandle const + getObjectHandle() const + { + return {obj}; + } + + protected: + QPDF_DLL_PRIVATE + QPDFObjectHandle + oh() + { + return {obj}; + } + QPDF_DLL_PRIVATE + QPDFObjectHandle const + oh() const + { + return {obj}; + } + QPDFObjectHandle oh_; +}; + +#endif // QPDFOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFOutlineDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFOutlineDocumentHelper.hh new file mode 100644 index 0000000..66b4481 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFOutlineDocumentHelper.hh @@ -0,0 +1,92 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEDOCUMENTHELPER_HH +#define QPDFOUTLINEDOCUMENTHELPER_HH + +#include +#include +#include +#include +#include + +#include +#include + +#include + +// This is a document helper for outlines, also known as bookmarks. Outlines are discussed in +// section 12.3.3 of the PDF spec (ISO-32000). With the help of QPDFOutlineObjectHelper, the +// outlines tree is traversed, and a bidirectional map is made between pages and outlines. See also +// QPDFOutlineObjectHelper. +class QPDFOutlineDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFOutlineDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Outlines structure. This is useful if you have modified the structure of the + // Outlines dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFOutlineDocumentHelper(QPDF&); + + ~QPDFOutlineDocumentHelper() override = default; + + QPDF_DLL + bool hasOutlines(); + + QPDF_DLL + std::vector getTopLevelOutlines(); + + // If the name is a name object, look it up in the /Dests key of the document catalog. If the + // name is a string, look it up in the name tree pointed to by the /Dests key of the names + // dictionary. + QPDF_DLL + QPDFObjectHandle resolveNamedDest(QPDFObjectHandle name); + + // Return a list outlines that are known to target the specified page. + QPDF_DLL + std::vector getOutlinesForPage(QPDFObjGen); + + class Accessor + { + friend class QPDFOutlineObjectHelper; + + static bool checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen og); + }; + + private: + void initializeByPage(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFOutlineObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFOutlineObjectHelper.hh new file mode 100644 index 0000000..108ec59 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFOutlineObjectHelper.hh @@ -0,0 +1,109 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEOBJECTHELPER_HH +#define QPDFOUTLINEOBJECTHELPER_HH + +#include +#include +#include + +class QPDFOutlineDocumentHelper; + +#include + +// This is an object helper for outline items. Outlines, also known as bookmarks, are described in +// section 12.3.3 of the PDF spec (ISO-32000). See comments below for details. +class QPDFOutlineObjectHelper: public QPDFObjectHelper +{ + public: + ~QPDFOutlineObjectHelper() override + { + // This must be cleared explicitly to avoid circular references that prevent cleanup of + // shared pointers. + m->parent = nullptr; + } + + // All constructors are private. You can only create one of these using + // QPDFOutlineDocumentHelper. + + // Return parent pointer. Returns a null pointer if this is a top-level outline. + QPDF_DLL + std::shared_ptr getParent(); + + // Return children as a list. + QPDF_DLL + std::vector getKids(); + + // Return the destination, regardless of whether it is named or explicit and whether it is + // directly provided or in a GoTo action. Returns a null object if the destination can't be + // determined. Named destinations can be resolved using the older root /Dest dictionary or the + // current names tree. + QPDF_DLL + QPDFObjectHandle getDest(); + + // Return the page that the outline points to. Returns a null object if the destination page + // can't be determined. + QPDF_DLL + QPDFObjectHandle getDestPage(); + + // Returns the value of /Count as present in the object, or 0 if not present. If count is + // positive, the outline is open. If negative, it is closed. Either way, the absolute value is + // the number of descendant items that would be visible if this were open. + QPDF_DLL + int getCount(); + + // Returns the title as a UTF-8 string. Returns an empty string if there is no title. + QPDF_DLL + std::string getTitle(); + + class Accessor + { + friend class QPDFOutlineDocumentHelper; + + static QPDFOutlineObjectHelper + create(QPDFObjectHandle oh, QPDFOutlineDocumentHelper& dh, int depth) + { + return {oh, dh, depth}; + } + }; + + private: + QPDFOutlineObjectHelper(QPDFObjectHandle, QPDFOutlineDocumentHelper&, int); + + class Members + { + friend class QPDFOutlineObjectHelper; + + public: + ~Members() = default; + + private: + Members(QPDFOutlineDocumentHelper& dh); + Members(Members const&) = delete; + + QPDFOutlineDocumentHelper& dh; + std::shared_ptr parent; + std::vector kids; + }; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageDocumentHelper.hh new file mode 100644 index 0000000..a2cd9f8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageDocumentHelper.hh @@ -0,0 +1,128 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEDOCUMENTHELPER_HH +#define QPDFPAGEDOCUMENTHELPER_HH + +#include +#include +#include + +#include + +#include + +#include + +class QPDFAcroFormDocumentHelper; + +class QPDFPageDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFPageDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Pages structure. This is useful if you have modified the Pages structure in + // a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageDocumentHelper(QPDF&); + + ~QPDFPageDocumentHelper() override = default; + + // Traverse page tree, and return all /Page objects wrapped in QPDFPageObjectHelper objects. + // Unlike with QPDF::getAllPages, the vector of pages returned by this call is not affected by + // additions or removals of pages. If you manipulate pages, you will have to call this again to + // get a new copy. Please see comments in QPDF.hh for getAllPages() for additional details. + QPDF_DLL + std::vector getAllPages(); + + // The PDF /Pages tree allows inherited values. Working with the pages of a pdf is much easier + // when the inheritance is resolved by explicitly setting the values in each /Page. + QPDF_DLL + void pushInheritedAttributesToPage(); + + // This calls QPDFPageObjectHelper::removeUnreferencedResources for every page in the document. + // See comments in QPDFPageObjectHelper.hh for details. + QPDF_DLL + void removeUnreferencedResources(); + + // Add a new page at the beginning or the end of the current pdf. The newpage parameter may be + // either a direct object, an indirect object from this QPDF, or an indirect object from another + // QPDF. If it is a direct object, it will be made indirect. If it is an indirect object from + // another QPDF, this method will call pushInheritedAttributesToPage on the other file and then + // copy the page to this QPDF using the same underlying code as copyForeignObject. At this + // stage, if the indirect object is already in the pages tree, a shallow copy is made to avoid + // adding the same page more than once. In version 10.3.1 and earlier, adding a page that + // already existed would throw an exception and could cause qpdf to crash on subsequent page + // insertions in some cases. Note that this means that, in some cases, the page actually added + // won't be exactly the same object as the one passed in. If you want to do subsequent + // modification on the page, you should retrieve it again. + // + // Note that you can call copyForeignObject directly to copy a page from a different file, but + // the resulting object will not be a page in the new file. You could do this, for example, to + // convert a page into a form XObject, though for that, you're better off using + // QPDFPageObjectHelper::getFormXObjectForPage. + // + // This method does not have any specific awareness of annotations or form fields, so if you + // just add a page without thinking about it, you might end up with two pages that share form + // fields or annotations. While the page may look fine, it will probably not function properly + // with regard to interactive features. To work around this, you should call + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations. A future version of qpdf will likely + // provide a higher-level interface for copying pages around that will handle document-level + // constructs in a less error-prone fashion. + + QPDF_DLL + void addPage(QPDFPageObjectHelper newpage, bool first); + + // Add new page before or after refpage. See comments for addPage for details about what newpage + // should be. + QPDF_DLL + void addPageAt(QPDFPageObjectHelper newpage, bool before, QPDFPageObjectHelper refpage); + + // Remove page from the pdf. + QPDF_DLL + void removePage(QPDFPageObjectHelper page); + + // For every annotation, integrate the annotation's appearance stream into the containing page's + // content streams, merge the annotation's resources with the page's resources, and remove the + // annotation from the page. Handles widget annotations associated with interactive form fields + // as a special case, including removing the /AcroForm key from the document catalog. The values + // passed to required_flags and forbidden_flags are passed along to + // QPDFAnnotationObjectHelper::getPageContentForAppearance. See comments there in + // QPDFAnnotationObjectHelper.hh for meanings of those flags. + QPDF_DLL + void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageLabelDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageLabelDocumentHelper.hh new file mode 100644 index 0000000..51e2265 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageLabelDocumentHelper.hh @@ -0,0 +1,99 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGELABELDOCUMENTHELPER_HH +#define QPDFPAGELABELDOCUMENTHELPER_HH + +#include + +#include +#include + +#include + +// Page labels are discussed in the PDF spec (ISO-32000) in section 12.4.2. +// +// Page labels are implemented as a number tree. Each key is a page index, numbered from 0. The +// values are dictionaries with the following keys, all optional: +// +// * /Type: if present, must be /PageLabel +// * /S: one of /D, /R, /r, /A, or /a for decimal, upper-case and lower-case Roman numeral, or +// upper-case and lower-case alphabetic +// * /P: if present, a fixed prefix string that is prepended to each page number +// * /St: the starting number, or 1 if not specified + +class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the PageLabels structure, which can be expensive. + QPDF_DLL + static QPDFPageLabelDocumentHelper& get(QPDF& qpdf); + + // Re-validate the PageLabels structure. This is useful if you have modified the structure of + // the PageLabels dictionary in a way that could have invalidated the structure. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageLabelDocumentHelper(QPDF&); + + ~QPDFPageLabelDocumentHelper() override = default; + + QPDF_DLL + bool hasPageLabels(); + + // Helper function to create a dictionary suitable for adding to the /PageLabels numbers tree. + QPDF_DLL + static QPDFObjectHandle + pageLabelDict(qpdf_page_label_e label_type, int start_num, std::string_view prefix); + + // Return a page label dictionary representing the page label for the given page. The page does + // not need to appear explicitly in the page label dictionary. This method will adjust /St as + // needed to produce a label that is suitable for the page. + QPDF_DLL + QPDFObjectHandle getLabelForPage(long long page_idx); + + // Append to the incoming vector a list of objects suitable for inclusion in a /PageLabels + // dictionary's /Nums field. start_idx and end_idx are the indexes to the starting and ending + // pages (inclusive) in the original file, and new_start_idx is the index to the first page in + // the new file. For example, if pages 10 through 12 of one file are being copied to a new file + // as pages 6 through 8, you would call getLabelsForPageRange(10, 12, 6), which would return as + // many entries as are required to add to the new file's PageLabels. This method fabricates a + // suitable entry even if the original document has no page labels. This behavior facilitates + // using this function to incrementally build up a page labels tree when merging files. + QPDF_DLL + void getLabelsForPageRange( + long long start_idx, + long long end_idx, + long long new_start_idx, + std::vector& new_labels); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGELABELDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageObjectHelper.hh new file mode 100644 index 0000000..ef8346e --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFPageObjectHelper.hh @@ -0,0 +1,423 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEOBJECTHELPER_HH +#define QPDFPAGEOBJECTHELPER_HH + +#include +#include +#include + +#include + +#include +#include + +class QPDFAcroFormDocumentHelper; + +// This is a helper class for page objects, but as of qpdf 10.1, many of the methods also work +// for form XObjects. When this is the case, it is noted in the comment. +class QPDFPageObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFPageObjectHelper(QPDFObjectHandle); + + ~QPDFPageObjectHelper() override = default; + + // PAGE ATTRIBUTES + + // The getAttribute method works with pages and form XObjects. It returns the value of the + // requested attribute from the page/form XObject's dictionary, taking inheritance from the + // pages tree into consideration. For pages, the attributes /MediaBox, /CropBox, /Resources, and + // /Rotate are inheritable, meaning that if they are not present directly on the page node, they + // may be inherited from ancestor nodes in the pages tree. + // + // There are two ways that an attribute can be "shared": + // + // * For inheritable attributes on pages, it may appear in a higher level node of the pages tree + // + // * For any attribute, the attribute may be an indirect object which may be referenced by more + // than one page/form XObject. + // + // If copy_if_shared is true, then this method will replace the attribute with a shallow copy if + // it is indirect or inherited and return the copy. You should do this if you are going to + // modify the returned object and want the modifications to apply to the current page/form + // XObject only. + QPDF_DLL + QPDFObjectHandle getAttribute(std::string const& name, bool copy_if_shared); + + // PAGE BOXES + // + // Pages have various types of boundary boxes. These are described in detail in the PDF + // specification (section 14.11.2 Page boundaries). They are, by key in the page dictionary: + // + // * /MediaBox -- boundaries of physical page + // * /CropBox -- clipping region of what is displayed + // * /BleedBox -- clipping region for production environments + // * /TrimBox -- dimensions of final printed page after trimming + // * /ArtBox -- extent of meaningful content including margins + // + // Of these, only /MediaBox is required. If any are absent, the + // fallback value for /CropBox is /MediaBox, and the fallback + // values for the other boxes are /CropBox. + // + // As noted above (PAGE ATTRIBUTES), /MediaBox and /CropBox can be inherited from parent nodes + // in the pages tree. The other boxes can't be inherited. + // + // When the comments below refer to the "effective value" of a box, this takes into + // consideration both inheritance through the pages tree (in the case of /MediaBox and /CropBox) + // and fallback values for missing attributes (for all except /MediaBox). + // + // For the methods below, copy_if_shared is passed to getAttribute and therefore refers only to + // indirect objects and values that are inherited through the pages tree. + // + // If copy_if_fallback is true, a copy is made if the object's value was obtained by falling + // back to a different box. + // + // The copy_if_shared and copy_if_fallback parameters carry across multiple layers. This is + // explained below. + // + // You should set copy_if_shared to true if you want to modify a bounding box for the current + // page without affecting other pages but you don't want to change the fallback behavior. For + // example, if you want to modify the /TrimBox for the current page only but have it continue to + // fall back to the value of /CropBox or /MediaBox if they are not defined, you could set + // copy_if_shared to true. + // + // You should set copy_if_fallback to true if you want to modify a specific box as distinct from + // any other box. For example, if you want to make /TrimBox differ from /CropBox, then you + // should set copy_if_fallback to true. + // + // The copy_if_fallback flags were added in qpdf 11. + // + // For example, suppose that neither /CropBox nor /TrimBox is present on a page but /CropBox is + // present in the page's parent node in the page tree. + // + // * getTrimBox(false, false) would return the /CropBox from the parent node. + // + // * getTrimBox(true, false) would make a shallow copy of the /CropBox from the parent node into + // the current node and return it. + // + // * getTrimBox(false, true) would make a shallow copy of the /CropBox from the parent node into + // /TrimBox of the current node and return it. + // + // * getTrimBox(true, true) would make a shallow copy of the /CropBox from the parent node into + // the current node, then make a shallow copy of the resulting copy to /TrimBox of the current + // node, and then return that. + // + // To illustrate how these parameters carry across multiple layers, suppose that neither + // /MediaBox, /CropBox, nor /TrimBox is present on a page but /MediaBox is present on the + // parent. In this case: + // + // * getTrimBox(false, false) would return the value of /MediaBox from the parent node. + // + // * getTrimBox(true, false) would copy /MediaBox to the current node and return it. + // + // * getTrimBox(false, true) would first copy /MediaBox from the parent to /CropBox, then copy + // /CropBox to /TrimBox, and then return the result. + // + // * getTrimBox(true, true) would first copy /MediaBox from the parent to the current page, then + // copy it to /CropBox, then copy /CropBox to /TrimBox, and then return the result. + // + // If you need different behavior, call getAttribute directly and take care of your own copying. + + // Return the effective MediaBox + QPDF_DLL + QPDFObjectHandle getMediaBox(bool copy_if_shared = false); + + // Return the effective CropBox. If not defined, fall back to MediaBox + QPDF_DLL + QPDFObjectHandle getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective BleedBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective TrimBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective ArtBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Iterate through XObjects, possibly recursing into form XObjects. This works with pages or + // form XObjects. Call action on each XObject for which selector, if specified, returns true. + // With no selector, calls action for every object. In addition to the object being passed to + // action, the containing XObject dictionary and key are passed in. Remember that the XObject + // dictionary may be shared, and the object may appear in multiple XObject dictionaries. + QPDF_DLL + void forEachXObject( + bool recursive, + std::function action, + std::function selector = nullptr); + // Only call action for images + QPDF_DLL + void forEachImage( + bool recursive, + std::function action); + // Only call action for form XObjects + QPDF_DLL + void forEachFormXObject( + bool recursive, + std::function action); + + // Returns an empty map if there are no images or no resources. Prior to qpdf 8.4.0, this + // function did not support inherited resources, but it does now. Return value is a map from + // XObject name to the image object, which is always a stream. Works with form XObjects as well + // as pages. This method does not recurse into nested form XObjects. For that, use forEachImage. + QPDF_DLL + std::map getImages(); + + // Old name -- calls getImages() + QPDF_DLL + std::map getPageImages(); + + // Returns an empty map if there are no form XObjects or no resources. Otherwise, returns a map + // of keys to form XObjects directly referenced from this page or form XObjects. This does not + // recurse into nested form XObjects. For that, use forEachFormXObject. + QPDF_DLL + std::map getFormXObjects(); + + // Converts each inline image to an external (normal) image if the size is at least the + // specified number of bytes. This method works with pages or form XObjects. By default, it + // recursively processes nested form XObjects. Pass true as shallow to avoid this behavior. + // Prior to qpdf 10.1, form XObjects were ignored, but this was considered a bug. + QPDF_DLL + void externalizeInlineImages(size_t min_size = 0, bool shallow = false); + + // Return the annotations in the page's "/Annots" list, if any. If only_subtype is non-empty, + // only include annotations of the given subtype. + QPDF_DLL + std::vector getAnnotations(std::string const& only_subtype = ""); + + // Returns a vector of stream objects representing the content streams for the given page. This + // routine allows the caller to not care whether there are one or more than one content streams + // for a page. + QPDF_DLL + std::vector getPageContents(); + + // Add the given object as a new content stream for this page. If parameter 'first' is true, add + // to the beginning. Otherwise, add to the end. This routine automatically converts the page + // contents to an array if it is a scalar, allowing the caller not to care what the initial + // structure is. You can call coalesceContentStreams() afterwards if you want to force it to be + // a single stream. + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + + // Rotate a page. If relative is false, set the rotation of the page to angle. Otherwise, add + // angle to the rotation of the page. Angle must be a multiple of 90. Adding 90 to the rotation + // rotates clockwise by 90 degrees. + QPDF_DLL + void rotatePage(int angle, bool relative); + + // Coalesce a page's content streams. A page's content may be a stream or an array of streams. + // If this page's content is an array, concatenate the streams into a single stream. This can be + // useful when working with files that split content streams in arbitrary spots, such as in the + // middle of a token, as that can confuse some software. You could also call this after calling + // addPageContents. + QPDF_DLL + void coalesceContentStreams(); + + // + // Content stream handling + // + + // Parse a page's contents through ParserCallbacks, described above. This method works whether + // the contents are a single stream or an array of streams. Call on a page object. Also works + // for form XObjects. + QPDF_DLL + void parseContents(QPDFObjectHandle::ParserCallbacks* callbacks); + // Old name + QPDF_DLL + void parsePageContents(QPDFObjectHandle::ParserCallbacks* callbacks); + + // Pass a page's or form XObject's contents through the given TokenFilter. If a pipeline is also + // provided, it will be the target of the write methods from the token filter. If a pipeline is + // not specified, any output generated by the token filter will be discarded. Use this interface + // if you need to pass a page's contents through filter for work purposes without having that + // filter automatically applied to the page's contents, as happens with addContentTokenFilter. + // See examples/pdf-count-strings.cc for an example. + QPDF_DLL + void filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Old name -- calls filterContents() + QPDF_DLL + void filterPageContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Pipe a page's contents through the given pipeline. This method works whether the contents are + // a single stream or an array of streams. Also works on form XObjects. + QPDF_DLL + void pipeContents(Pipeline* p); + // Old name + QPDF_DLL + void pipePageContents(Pipeline* p); + + // Attach a token filter to a page's contents. If the page's contents is an array of streams, it + // is automatically coalesced. The token filter is applied to the page's contents as a single + // stream. Also works on form XObjects. + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + + // A page's resources dictionary maps names to objects elsewhere in the file. This method walks + // through a page's contents and keeps tracks of which resources are referenced somewhere in the + // contents. Then it removes from the resources dictionary any object that is not referenced in + // the contents. This operation is most useful after calling + // QPDFPageDocumentHelper::pushInheritedAttributesToPage(). This method is used by page + // splitting code to avoid copying unused objects in files that used shared resource + // dictionaries across multiple pages. This method recurses into form XObjects and can be called + // with a form XObject as well as a page. + QPDF_DLL + void removeUnreferencedResources(); + + // Return a new QPDFPageObjectHelper that is a duplicate of the page. The returned object is an + // indirect object that is ready to be inserted into the same or a different QPDF object using + // any of the addPage methods in QPDFPageDocumentHelper or QPDF. Without calling one of those + // methods, the page will not be added anywhere. The new page object shares all content streams + // and indirect object resources with the original page, so if you are going to modify the + // contents or other aspects of the page, you will need to handling copying of the component + // parts separately. + QPDF_DLL + QPDFPageObjectHelper shallowCopyPage(); + + // Return a transformation matrix whose effect is the same as the page's /Rotate and /UserUnit + // parameters. If invert is true, return a matrix whose effect is the opposite. The regular + // matrix is suitable for taking something from this page to put elsewhere, and the second one + // is suitable for putting something else onto this page. The page's TrimBox is used as the + // bounding box for purposes of computing the matrix. + QPDF_DLL + QPDFObjectHandle::Matrix getMatrixForTransformations(bool invert = false); + + // Return a form XObject that draws this page. This is useful for n-up operations, underlay, + // overlay, thumbnail generation, or any other case in which it is useful to replicate the + // contents of a page in some other context. The dictionaries are shallow copies of the original + // page dictionary, and the contents are coalesced from the page's contents. The resulting + // object handle is not referenced anywhere. If handle_transformations is true, the resulting + // form XObject's /Matrix will be set to replicate rotation (/Rotate) and scaling (/UserUnit) in + // the page's dictionary. In this way, the page's transformations will be preserved when placing + // this object on another page. + QPDF_DLL + QPDFObjectHandle getFormXObjectForPage(bool handle_transformations = true); + + // Return content stream text that will place the given form XObject (fo) using the resource + // name "name" on this page centered within the given rectangle. If invert_transformations is + // true, the effect of any rotation (/Rotate) and scaling (/UserUnit) applied to the current + // page will be inverted in the form XObject placement. This will cause the form XObject's + // absolute orientation to be preserved. You could overlay one page on another by calling + // getFormXObjectForPage on the original page, QPDFObjectHandle::getUniqueResourceName on the + // destination page's Resources dictionary to generate a name for the resulting object, and + // calling placeFormXObject on the destination page. Then insert the new fo (or, if it comes + // from a different file, the result of calling copyForeignObject on it) into the resources + // dictionary using name, and append or prepend the content to the page's content streams. See + // the overlay/underlay code in qpdf.cc or examples/pdf-overlay-page.cc for an example. From + // qpdf 10.0.0, the allow_shrink and allow_expand parameters control whether the form XObject is + // allowed to be shrunk or expanded to stay within or maximally fill the destination rectangle. + // The default values are for backward compatibility with the pre-10.0.0 behavior. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Alternative version that also fills in the transformation matrix that was used. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + QPDFMatrix& cm, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Return the transformation matrix that translates from the given form XObject's coordinate + // system into the given rectangular region on the page. The parameters have the same meaning as + // for placeFormXObject. + QPDF_DLL + QPDFMatrix getMatrixForFormXObjectPlacement( + QPDFObjectHandle fo, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // If a page is rotated using /Rotate in the page's dictionary, instead rotate the page by the + // same amount by altering the contents and removing the /Rotate key. This method adjusts the + // various page bounding boxes (/MediaBox, etc.) so that the page will have the same semantics. + // This can be useful to work around problems with PDF applications that can't properly handle + // rotated pages. If a QPDFAcroFormDocumentHelper is provided, it will be used for resolving any + // form fields that have to be rotated. If not, one will be created inside the function, which + // is less efficient. + QPDF_DLL + void flattenRotation(QPDFAcroFormDocumentHelper* afdh = nullptr); + + // Copy annotations from another page into this page. The other page may be from the same QPDF + // or from a different QPDF. Each annotation's rectangle is transformed by the given matrix. If + // the annotation is a widget annotation that is associated with a form field, the form field is + // copied into this document's AcroForm dictionary as well. You can use this to copy annotations + // from a page that was converted to a form XObject and added to another page. For example of + // this, see examples/pdf-overlay-page.cc. This method calls + // QPDFAcroFormDocumentHelper::transformAnnotations, which will copy annotations and form fields + // so that you can copy annotations from a source page to any number of other pages, even with + // different matrices, and maintain independence from the original annotations. See also + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations, which can be used if you copy a page and + // want to repair the annotations on the destination page to make them independent from the + // original page's annotations. + // + // If you pass in a QPDFAcroFormDocumentHelper*, the method will use that instead of creating + // one in the function. Creating QPDFAcroFormDocumentHelper objects is expensive, so if you're + // doing a lot of copying, it can be more efficient to create these outside and pass them in. + QPDF_DLL + void copyAnnotations( + QPDFPageObjectHelper from_page, + QPDFMatrix const& cm = QPDFMatrix(), + QPDFAcroFormDocumentHelper* afdh = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + private: + QPDFObjectHandle getAttribute( + std::string const& name, + bool copy_if_shared, + std::function get_fallback, + bool copy_if_fallback); + static bool + removeUnreferencedResourcesHelper(QPDFPageObjectHelper ph, std::set& unresolved); + + class Members + { + friend class QPDFPageObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFStreamFilter.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFStreamFilter.hh new file mode 100644 index 0000000..5cba242 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFStreamFilter.hh @@ -0,0 +1,67 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSTREAMFILTER_HH +#define QPDFSTREAMFILTER_HH + +#include +#include +#include + +class QPDF_DLL_CLASS QPDFStreamFilter +{ + public: + QPDFStreamFilter() = default; + + virtual ~QPDFStreamFilter() = default; + + // A QPDFStreamFilter class must implement, at a minimum, setDecodeParms() and + // getDecodePipeline(). QPDF will always call setDecodeParms() before calling + // getDecodePipeline(). It is expected that you will store any needed information from + // decode_parms (or the decode_parms object itself) in your instance so that it can be used to + // construct the decode pipeline. + + // Return a boolean indicating whether your filter can proceed with the given /DecodeParms. The + // default implementation accepts a null object and rejects everything else. + QPDF_DLL + virtual bool setDecodeParms(QPDFObjectHandle decode_parms); + + // Return a pipeline that will decode data encoded with your filter. Your implementation must + // ensure that the pipeline is deleted when the instance of your class is destroyed. + QPDF_DLL + virtual Pipeline* getDecodePipeline(Pipeline* next) = 0; + + // If your filter implements "specialized" compression or lossy compression, override one or + // both of these methods. The default implementations return false. See comments in QPDFWriter + // for details. QPDF defines specialized compression as non-lossy compression not intended for + // general-purpose data. qpdf, by default, doesn't mess with streams that are compressed with + // specialized compression, the idea being that the decision to use that compression scheme + // would fall outside of what QPDFWriter would know anything about, so any attempt to decode and + // re-encode would probably be undesirable. + QPDF_DLL + virtual bool isSpecializedCompression(); + QPDF_DLL + virtual bool isLossyCompression(); + + private: + QPDFStreamFilter(QPDFStreamFilter const&) = delete; + QPDFStreamFilter& operator=(QPDFStreamFilter const&) = delete; +}; + +#endif // QPDFSTREAMFILTER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFSystemError.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFSystemError.hh new file mode 100644 index 0000000..94e0ab0 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFSystemError.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSYSTEMERROR_HH +#define QPDFSYSTEMERROR_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error +{ + public: + QPDF_DLL + QPDFSystemError(std::string const& description, int system_errno); + + ~QPDFSystemError() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. + + QPDF_DLL + std::string const& getDescription() const; + QPDF_DLL + int getErrno() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat(std::string const& description, int system_errno); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + std::string description; + int system_errno; +}; + +#endif // QPDFSYSTEMERROR_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFTokenizer.hh new file mode 100644 index 0000000..94dae1a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFTokenizer.hh @@ -0,0 +1,218 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFTOKENIZER_HH +#define QPDFTOKENIZER_HH + +#include + +#include + +#include +#include +#include + +namespace qpdf +{ + class Tokenizer; + namespace impl + { + class Parser; + } +} // namespace qpdf + +class QPDFTokenizer +{ + public: + // Token type tt_eof is only returned of allowEOF() is called on the tokenizer. tt_eof was + // introduced in QPDF version 4.1. tt_space, tt_comment, and tt_inline_image were added in QPDF + // version 8. + enum token_type_e { + tt_bad, + tt_array_close, + tt_array_open, + tt_brace_close, + tt_brace_open, + tt_dict_close, + tt_dict_open, + tt_integer, + tt_name, + tt_real, + tt_string, + tt_null, + tt_bool, + tt_word, + tt_eof, + tt_space, + tt_comment, + tt_inline_image, + }; + + class Token + { + public: + Token() : + type(tt_bad) + { + } + QPDF_DLL + Token(token_type_e type, std::string const& value); + Token( + token_type_e type, + std::string const& value, + std::string raw_value, + std::string error_message) : + type(type), + value(value), + raw_value(raw_value), + error_message(error_message) + { + } + token_type_e + getType() const + { + return this->type; + } + std::string const& + getValue() const + { + return this->value; + } + std::string const& + getRawValue() const + { + return this->raw_value; + } + std::string const& + getErrorMessage() const + { + return this->error_message; + } + bool + operator==(Token const& rhs) const + { + // Ignore fields other than type and value + return ( + (this->type != tt_bad) && (this->type == rhs.type) && (this->value == rhs.value)); + } + bool + isInteger() const + { + return this->type == tt_integer; + } + bool + isWord() const + { + return this->type == tt_word; + } + bool + isWord(std::string const& value) const + { + return this->type == tt_word && this->value == value; + } + + private: + token_type_e type; + std::string value; + std::string raw_value; + std::string error_message; + }; + + QPDF_DLL + QPDFTokenizer(); + + QPDF_DLL + ~QPDFTokenizer(); + + // If called, treat EOF as a separate token type instead of an error. This was introduced in + // QPDF 4.1 to facilitate tokenizing content streams. + QPDF_DLL + void allowEOF(); + + // If called, readToken will return "ignorable" tokens for space and comments. This was added in + // QPDF 8. + QPDF_DLL + void includeIgnorable(); + + // There are two modes of operation: push and pull. The pull method is easier but requires an + // input source. The push method is more complicated but can be used to tokenize a stream of + // incoming characters in a pipeline. + + // Push mode: + + // deprecated, please see + + // Keep presenting characters with presentCharacter() and presentEOF() and calling getToken() + // until getToken() returns true. When it does, be sure to check unread_ch and to unread ch if + // it is true. If these are called when a token is available, an exception will be thrown. + QPDF_DLL + void presentCharacter(char ch); + QPDF_DLL + void presentEOF(); + + // If a token is available, return true and initialize token with the token, unread_char with + // whether or not we have to unread the last character, and if unread_char, ch with the + // character to unread. + QPDF_DLL + bool getToken(Token& token, bool& unread_char, char& ch); + + // This function returns true of the current character is between tokens (i.e., white space that + // is not part of a string) or is part of a comment. A tokenizing filter can call this to + // determine whether to output the character. + [[deprecated("see ")]] QPDF_DLL bool + betweenTokens(); + + // Pull mode: + + // Read a token from an input source. Context describes the context in which the token is being + // read and is used in the exception thrown if there is an error. After a token is read, the + // position of the input source returned by input->tell() points to just after the token, and + // the input source's "last offset" as returned by input->getLastOffset() points to the + // beginning of the token. + QPDF_DLL + Token readToken( + InputSource& input, std::string const& context, bool allow_bad = false, size_t max_len = 0); + QPDF_DLL + Token readToken( + std::shared_ptr input, + std::string const& context, + bool allow_bad = false, + size_t max_len = 0); + + // Calling this method puts the tokenizer in a state for reading inline images. You should call + // this method after reading the character following the ID operator. In that state, it will + // return all data up to BUT NOT INCLUDING the next EI token. After you call this method, the + // next call to readToken (or the token created next time getToken returns true) will either be + // tt_inline_image or tt_bad. This is the only way readToken + // returns a tt_inline_image token. + QPDF_DLL + void expectInlineImage(std::shared_ptr input); + QPDF_DLL + void expectInlineImage(InputSource& input); + + private: + friend class qpdf::impl::Parser; + + QPDFTokenizer(QPDFTokenizer const&) = delete; + QPDFTokenizer& operator=(QPDFTokenizer const&) = delete; + + std::unique_ptr m; +}; + +#endif // QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFUsage.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFUsage.hh new file mode 100644 index 0000000..3c5da1b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFUsage.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFUSAGE_HH +#define QPDFUSAGE_HH + +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error +{ + public: + QPDF_DLL + QPDFUsage(std::string const& msg); + ~QPDFUsage() noexcept override = default; +}; + +#endif // QPDFUSAGE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFWriter.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFWriter.hh new file mode 100644 index 0000000..3c3c0b9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFWriter.hh @@ -0,0 +1,455 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFWRITER_HH +#define QPDFWRITER_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace qpdf +{ + class Writer; +} + +class QPDF; + +// This class implements a simple writer for saving QPDF objects to new PDF files. See comments +// through the header file for additional details. +class QPDFWriter +{ + public: + // Construct a QPDFWriter object without specifying output. You must call one of the output + // setting routines defined below. + QPDF_DLL + QPDFWriter(QPDF& pdf); + + // Create a QPDFWriter object that writes its output to a file or to stdout. This is equivalent + // to using the previous constructor and then calling setOutputFilename(). See + // setOutputFilename() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* filename); + + // Create a QPDFWriter object that writes its output to an already open FILE*. This is + // equivalent to calling the first constructor and then calling setOutputFile(). See + // setOutputFile() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* description, FILE* file, bool close_file); + + ~QPDFWriter() = default; + + class QPDF_DLL_CLASS ProgressReporter + { + public: + QPDF_DLL + virtual ~ProgressReporter(); + + // This method is called with a value from 0 to 100 to indicate approximate progress through + // the write process. See registerProgressReporter. + virtual void reportProgress(int) = 0; + }; + + // This is a progress reporter that takes a function. It is used by the C APIs, but it is + // available if you want to just register a C function as a handler. + class QPDF_DLL_CLASS FunctionProgressReporter: public ProgressReporter + { + public: + QPDF_DLL + FunctionProgressReporter(std::function); + QPDF_DLL + ~FunctionProgressReporter() override; + QPDF_DLL + void reportProgress(int) override; + + private: + std::function handler; + }; + + // Setting Output. Output may be set only one time. If you don't use the filename version of + // the QPDFWriter constructor, you must call exactly one of these methods. + + // Passing nullptr as filename means write to stdout. QPDFWriter will create a zero-length + // output file upon construction. If write fails, the empty or partially written file will not + // be deleted. This is by design: sometimes the partial file may be useful for tracking down + // problems. If your application doesn't want the partially written file to be left behind, you + // should delete it if the eventual call to write fails. + QPDF_DLL + void setOutputFilename(char const* filename); + + // Write to the given FILE*, which must be opened by the caller. If close_file is true, + // QPDFWriter will close the file. Otherwise, the caller must close the file. The file does not + // need to be seekable; it will be written to in a single pass. It must be open in binary mode. + QPDF_DLL + void setOutputFile(char const* description, FILE* file, bool close_file); + + // Indicate that QPDFWriter should create a memory buffer to contain the final PDF file. Obtain + // the memory by calling getBuffer(). + QPDF_DLL + void setOutputMemory(); + + // Return the buffer object containing the PDF file. If setOutputMemory() has been called, this + // method may be called exactly one time after write() has returned. The caller is responsible + // for deleting the buffer when done. See also getBufferSharedPointer(). + QPDF_DLL + Buffer* getBuffer(); + + // Return getBuffer() in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // Supply your own pipeline object. Output will be written to this pipeline, and QPDFWriter + // will call finish() on the pipeline. It is the caller's responsibility to manage the memory + // for the pipeline. The pipeline is never deleted by QPDFWriter, which makes it possible for + // you to call additional methods on the pipeline after the writing is finished. + QPDF_DLL + void setOutputPipeline(Pipeline*); + + // Setting Parameters + + // Set the value of object stream mode. In disable mode, we never generate any object streams. + // In preserve mode, we preserve object stream structure from the original file. In generate + // mode, we generate our own object streams. In all cases, we generate a conventional + // cross-reference table if there are no object streams and a cross-reference stream if there + // are object streams. The default is o_preserve. + QPDF_DLL + void setObjectStreamMode(qpdf_object_stream_e); + + // Set value of stream data mode. This is an older interface. Instead of using this, prefer + // setCompressStreams() and setDecodeLevel(). This method is retained for compatibility, but it + // does not cover the full range of available configurations. The mapping between this and the + // new methods is as follows: + // + // qpdf_s_uncompress: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_generalized) + // qpdf_s_preserve: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_none) + // qpdf_s_compress: + // setCompressStreams(true) + // setDecodeLevel(qpdf_dl_generalized) + // + // The default is qpdf_s_compress. + QPDF_DLL + void setStreamDataMode(qpdf_stream_data_e); + + // If true, compress any uncompressed streams when writing them. Metadata streams are a special + // case and are not compressed even if this is true. This is true by default for QPDFWriter. If + // you want QPDFWriter to leave uncompressed streams uncompressed, pass false to this method. + QPDF_DLL + void setCompressStreams(bool); + + // When QPDFWriter encounters streams, this parameter controls the behavior with respect to + // attempting to apply any filters to the streams when copying to the output. The decode levels + // are as follows: + // + // qpdf_dl_none: Do not attempt to apply any filters. Streams remain as they appear in the + // original file. Note that uncompressed streams may still be compressed on output. You can + // disable that by calling setCompressStreams(false). + // + // qpdf_dl_generalized: This is the default. QPDFWriter will apply LZWDecode, ASCII85Decode, + // ASCIIHexDecode, and FlateDecode filters on the input. When combined with + // setCompressStreams(true), which is the default, the effect of this is that streams filtered + // with these older and less efficient filters will be recompressed with the Flate filter. By + // default, as a special case, if a stream is already compressed with FlateDecode and + // setCompressStreams is enabled, the original compressed data will be preserved. This behavior + // can be overridden by calling setRecompressFlate(true). + // + // qpdf_dl_specialized: In addition to uncompressing the generalized compression formats, + // supported non-lossy compression will also be decoded. At present, this includes the + // RunLengthDecode filter. + // + // qpdf_dl_all: In addition to generalized and non-lossy specialized filters, supported lossy + // compression filters will be applied. At present, this includes DCTDecode (JPEG) compression. + // Note that compressing the resulting data with DCTDecode again will accumulate loss, so avoid + // multiple compression and decompression cycles. This is mostly useful for retrieving image + // data. + QPDF_DLL + void setDecodeLevel(qpdf_stream_decode_level_e); + + // By default, when both the input and output contents of a stream are compressed with Flate, + // qpdf does not uncompress and recompress the stream. Passing true here causes it to do so. + // This can be useful if recompressing all streams with a higher compression level, which can be + // set by calling the static method Pl_Flate::setCompressionLevel. + QPDF_DLL + void setRecompressFlate(bool); + + // Set value of content stream normalization. The default is "false". If true, we attempt to + // normalize newlines inside of content streams. Some constructs such as inline images may + // thwart our efforts. There may be some cases where this can damage the content stream. This + // flag should be used only for debugging and experimenting with PDF content streams. Never use + // it for production files. + QPDF_DLL + void setContentNormalization(bool); + + // Set QDF mode. QDF mode causes special "pretty printing" of PDF objects, adds comments for + // easier perusing of files. Resulting PDF files can be edited in a text editor and then run + // through fix-qdf to update cross reference tables and stream lengths. + QPDF_DLL + void setQDFMode(bool); + + // Preserve unreferenced objects. The default behavior is to discard any object that is not + // visited during a traversal of the object structure from the trailer. + QPDF_DLL + void setPreserveUnreferencedObjects(bool); + + // Always write a newline before the endstream keyword. This helps with PDF/A compliance, though + // it is not sufficient for it. + QPDF_DLL + void setNewlineBeforeEndstream(bool); + + // Set the minimum PDF version. If the PDF version of the input file (or previously set minimum + // version) is less than the version passed to this method, the PDF version of the output file + // will be set to this value. If the original PDF file's version or previously set minimum + // version is already this version or later, the original file's version will be used. + // QPDFWriter automatically sets the minimum version to 1.4 when R3 encryption parameters are + // used, and to 1.5 when object streams are used. + QPDF_DLL + void setMinimumPDFVersion(std::string const&, int extension_level = 0); + QPDF_DLL + void setMinimumPDFVersion(PDFVersion const&); + + // Force the PDF version of the output file to be a given version. Use of this function may + // create PDF files that will not work properly with older PDF viewers. When a PDF version is + // set using this function, qpdf will use this version even if the file contains features that + // are not supported in that version of PDF. In other words, you should only use this function + // if you are sure the PDF file in question has no features of newer versions of PDF or if you + // are willing to create files that old viewers may try to open but not be able to properly + // interpret. If any encryption has been applied to the document either explicitly or by + // preserving the encryption of the source document, forcing the PDF version to a value too low + // to support that type of encryption will explicitly disable decryption. Additionally, forcing + // to a version below 1.5 will disable object streams. + QPDF_DLL + void forcePDFVersion(std::string const&, int extension_level = 0); + + // Provide additional text to insert in the PDF file somewhere near the beginning of the file. + // This can be used to add comments to the beginning of a PDF file, for example, if those + // comments are to be consumed by some other application. No checks are performed to ensure + // that the text inserted here is valid PDF. If you want to insert multiline comments, you will + // need to include \n in the string yourself and start each line with %. An extra newline will + // be appended if one is not already present at the end of your text. + QPDF_DLL + void setExtraHeaderText(std::string const&); + + // Causes a deterministic /ID value to be generated. When this is set, the current time and + // output file name are not used as part of /ID generation. Instead, a digest of all significant + // parts of the output file's contents is included in the /ID calculation. Use of a + // deterministic /ID can be handy when it is desirable for a repeat of the same qpdf operation + // on the same inputs being written to the same outputs with the same parameters to generate + // exactly the same results. This feature is incompatible with encrypted files because, for + // encrypted files, the /ID is generated before any part of the file is written since it is an + // input to the encryption process. + QPDF_DLL + void setDeterministicID(bool); + + // Cause a static /ID value to be generated. Use only in test suites. See also + // setDeterministicID. + QPDF_DLL + void setStaticID(bool); + + // Use a fixed initialization vector for AES-CBC encryption. This is not secure. It should be + // used only in test suites for creating predictable encrypted output. + QPDF_DLL + void setStaticAesIV(bool); + + // Suppress inclusion of comments indicating original object IDs when writing QDF files. This + // can also be useful for testing, particularly when using comparison of two qdf files to + // determine whether two PDF files have identical content. + QPDF_DLL + void setSuppressOriginalObjectIDs(bool); + + // Preserve encryption. The default is true unless prefiltering, content normalization, or qdf + // mode has been selected in which case encryption is never preserved. Encryption is also not + // preserved if we explicitly set encryption parameters. + QPDF_DLL + void setPreserveEncryption(bool); + + // Copy encryption parameters from another QPDF object. If you want to copy encryption from the + // object you are writing, call setPreserveEncryption(true) instead. + QPDF_DLL + void copyEncryptionParameters(QPDF&); + + // Set up for encrypted output. User and owner password both must be specified. Either or both + // may be the empty string. Note that qpdf does not apply any special treatment to the empty + // string, which makes it possible to create encrypted files with empty owner passwords and + // non-empty user passwords or with the same password for both user and owner. Some PDF reading + // products don't handle such files very well. Enabling encryption disables stream prefiltering + // and content normalization. Note that setting R2 encryption parameters sets the PDF version + // to at least 1.3, setting R3 encryption parameters pushes the PDF version number to at + // least 1.4, setting R4 parameters pushes the version to at least 1.5, or if AES is used, 1.6, + // and setting R5 or R6 parameters pushes the version to at least 1.7 with extension level 3. + // + // Note about Unicode passwords: the PDF specification requires passwords to be encoded with PDF + // Doc encoding for R <= 4 and UTF-8 for R >= 5. In all cases, these methods take strings of + // bytes as passwords. It is up to the caller to ensure that passwords are properly encoded. The + // qpdf command-line tool tries to do this, as discussed in the manual. If you are doing this + // from your own application, QUtil contains many transcoding functions that could be useful to + // you, most notably utf8_to_pdf_doc. + + // R2 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR2EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_print, + bool allow_modify, + bool allow_extract, + bool allow_annotate); + // R3 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR3EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print); + // When use_aes=false, this call enables R4 with RC4, which is a weak cryptographic algorithm. + // Even with use_aes=true, the overall encryption scheme is weak. Don't use it unless you have + // to. See "Weak Cryptography" in the manual. This encryption format is deprecated in the + // PDF 2.0 specification. + QPDF_DLL + void setR4EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata, + bool use_aes); + // R5 is deprecated. Do not use it for production use. Writing R5 is supported by qpdf + // primarily to generate test files for applications that may need to test R5 support. + QPDF_DLL + void setR5EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata); + // This is the only password-based encryption format supported by the PDF specification. + QPDF_DLL + void setR6EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata_aes); + + // Create linearized output. Disables qdf mode, content normalization, and stream prefiltering. + QPDF_DLL + void setLinearization(bool); + + // For debugging QPDF: provide the name of a file to write pass1 of linearization to. The only + // reason to use this is to debug QPDF. To linearize, QPDF writes out the file in two passes. + // Usually the first pass is discarded, but lots of computations are made in pass 1. If a + // linearized file comes out wrong, it can be helpful to look at the first pass. + QPDF_DLL + void setLinearizationPass1Filename(std::string const&); + + // Create PCLm output. This is only useful for clients that know how to create PCLm files. If a + // file is structured exactly as PCLm requires, this call will tell QPDFWriter to write the PCLm + // header, create certain unreferenced streams required by the standard, and write the objects + // in the required order. Calling this on an ordinary PDF serves no purpose. There is no + // command-line argument that causes this method to be called. + QPDF_DLL + void setPCLm(bool); + + // If you want to be notified of progress, derive a class from ProgressReporter and override the + // reportProgress method. + QPDF_DLL + void registerProgressReporter(std::shared_ptr); + + // Return the PDF version that will be written into the header. Calling this method does all the + // preparation for writing, so it is an error to call any methods that may cause a change to the + // version. Adding new objects to the original file after calling this may also cause problems. + // It is safe to update existing objects or stream contents after calling this method, e.g., to + // include the final version number in metadata. + QPDF_DLL + std::string getFinalVersion(); + + // Write the final file. There is no expectation of being able to call write() more than once. + QPDF_DLL + void write(); + + // Return renumbered ObjGen that was written into the final file. This method can be used after + // calling write(). + QPDF_DLL + QPDFObjGen getRenumberedObjGen(QPDFObjGen); + + // Return XRef entry that was written into the final file. This method can be used after calling + // write(). + QPDF_DLL + std::map getWrittenXRefTable(); + + // The following structs / classes are not part of the public API. + struct Object; + struct NewObject; + class ObjTable; + class NewObjTable; + + private: + friend class qpdf::Writer; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFWRITER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFXRefEntry.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFXRefEntry.hh new file mode 100644 index 0000000..3739131 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QPDFXRefEntry.hh @@ -0,0 +1,73 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFXREFENTRY_HH +#define QPDFXREFENTRY_HH + +#include +#include + +class QPDFXRefEntry +{ + public: + // Type constants are from the PDF spec section "Cross-Reference Streams": + // 0 = free entry; not used + // 1 = "uncompressed"; field 1 = offset + // 2 = "compressed"; field 1 = object stream number, field 2 = index + + // Create a type 0 "free" entry. + QPDF_DLL + QPDFXRefEntry(); + QPDF_DLL + QPDFXRefEntry(int type, qpdf_offset_t field1, int field2); + // Create a type 1 "uncompressed" entry. + QPDFXRefEntry(qpdf_offset_t offset) : + type(1), + field1(offset) + { + } + // Create a type 2 "compressed" entry. + QPDFXRefEntry(int stream_number, int index) : + type(2), + field1(stream_number), + field2(index) + { + } + + QPDF_DLL + int getType() const; + QPDF_DLL + qpdf_offset_t getOffset() const; // only for type 1 + QPDF_DLL + int getObjStreamNumber() const; // only for type 2 + QPDF_DLL + int getObjStreamIndex() const; // only for type 2 + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created. + + // The layout can be changed to reduce the size from 24 to 16 bytes. However, this would have a + // definite runtime cost. + int type{0}; + qpdf_offset_t field1{0}; + int field2{0}; +}; + +#endif // QPDFXREFENTRY_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QTC.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QTC.hh new file mode 100644 index 0000000..a5ecadf --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QTC.hh @@ -0,0 +1,43 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QTC_HH +#define QTC_HH + +#include + +// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC calls in any code that +// includes this file, but QTC will still be built into the library. That way, it is possible to +// build and package qpdf with QPDF_DISABLE_QTC while still making QTC::TC available to end users. + +namespace QTC +{ + QPDF_DLL + void TC_real(char const* const scope, char const* const ccase, int n = 0); + + inline void + TC(char const* const scope, char const* const ccase, int n = 0) + { +#ifndef QPDF_DISABLE_QTC + TC_real(scope, ccase, n); +#endif // QPDF_DISABLE_QTC + } +}; // namespace QTC + +#endif // QTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QUtil.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QUtil.hh new file mode 100644 index 0000000..18d6083 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/QUtil.hh @@ -0,0 +1,512 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QUTIL_HH +#define QUTIL_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RandomDataProvider; +class Pipeline; + +namespace QUtil +{ + // This is a collection of useful utility functions that don't really go anywhere else. + QPDF_DLL + std::string int_to_string(long long, int length = 0); + QPDF_DLL + std::string uint_to_string(unsigned long long, int length = 0); + QPDF_DLL + std::string int_to_string_base(long long, int base, int length = 0); + QPDF_DLL + std::string uint_to_string_base(unsigned long long, int base, int length = 0); + QPDF_DLL + std::string double_to_string(double, int decimal_places = 0, bool trim_trailing_zeroes = true); + + // These string to number methods throw std::runtime_error on underflow/overflow. + QPDF_DLL + long long string_to_ll(char const* str); + QPDF_DLL + int string_to_int(char const* str); + QPDF_DLL + unsigned long long string_to_ull(char const* str); + QPDF_DLL + unsigned int string_to_uint(char const* str); + + // Returns true if this exactly represents a long long. The determination is made by converting + // the string to a long long, then converting the result back to a string, and then comparing + // that result with the original string. + QPDF_DLL + bool is_long_long(char const* str); + + // Pipeline's write method wants unsigned char*, but we often have some other type of string. + // These methods do combinations of const_cast and reinterpret_cast to give us an unsigned + // char*. They should only be used when it is known that it is safe. None of the pipelines in + // qpdf modify the data passed to them, so within qpdf, it should always be safe. + QPDF_DLL + unsigned char* unsigned_char_pointer(std::string const& str); + QPDF_DLL + unsigned char* unsigned_char_pointer(char const* str); + + // Throw QPDFSystemError, which is derived from std::runtime_error, with a string formed by + // appending to "description: " the standard string corresponding to the current value of errno. + // You can retrieve the value of errno by calling getErrno() on the QPDFSystemError. Prior to + // qpdf 8.2.0, this method threw system::runtime_error directly, but since QPDFSystemError is + // derived from system::runtime_error, old code that specifically catches std::runtime_error + // will still work. + QPDF_DLL + void throw_system_error(std::string const& description); + + // The status argument is assumed to be the return value of a standard library call that sets + // errno when it fails. If status is -1, convert the current value of errno to a + // std::runtime_error that includes the standard error string. Otherwise, return status. + QPDF_DLL + int os_wrapper(std::string const& description, int status); + + // If the open fails, throws std::runtime_error. Otherwise, the FILE* is returned. The filename + // should be UTF-8 encoded, even on Windows. It will be converted as needed on Windows. + QPDF_DLL + FILE* safe_fopen(char const* filename, char const* mode); + + // The FILE* argument is assumed to be the return of fopen. If null, throw std::runtime_error. + // Otherwise, return the FILE* argument. + QPDF_DLL + FILE* fopen_wrapper(std::string const&, FILE*); + + // This is a little class to help with automatic closing files. You can do something like + // + // QUtil::FileCloser fc(QUtil::safe_fopen(filename, "rb")); + // + // and then use fc.f to the file. Be sure to actually declare a variable of type FileCloser. + // Using it as a temporary won't work because it will close the file as soon as it goes out of + // scope. + class FileCloser + { + public: + FileCloser(FILE* f) : + f(f) + { + } + + ~FileCloser() + { + if (f) { + fclose(f); + f = nullptr; + } + } + + FILE* f; + }; + + // Attempt to open the file read only and then close again + QPDF_DLL + bool file_can_be_opened(char const* filename); + + // Wrap around off_t versions of fseek and ftell if available + QPDF_DLL + int seek(FILE* stream, qpdf_offset_t offset, int whence); + QPDF_DLL + qpdf_offset_t tell(FILE* stream); + + QPDF_DLL + bool same_file(char const* name1, char const* name2); + + QPDF_DLL + void remove_file(char const* path); + + // rename_file will overwrite newname if it exists + QPDF_DLL + void rename_file(char const* oldname, char const* newname); + + // Write the contents of filename as a binary file to the pipeline. + QPDF_DLL + void pipe_file(char const* filename, Pipeline* p); + + // Return a function that will send the contents of the given file through the given pipeline as + // binary data. + QPDF_DLL + std::function file_provider(std::string const& filename); + + // Return the last path element. On Windows, either / or \ are path separators. Otherwise, only + // / is a path separator. Strip any trailing path separators. Then, if any path separators + // remain, return everything after the last path separator. Otherwise, return the whole string. + // As a special case, if a string consists entirely of path separators, the first character is + // returned. + QPDF_DLL + std::string path_basename(std::string const& filename); + + // Returns a dynamically allocated copy of a string that the caller has to delete with delete[]. + QPDF_DLL + char* copy_string(std::string const&); + + // Returns a shared_ptr with the correct deleter. + QPDF_DLL + std::shared_ptr make_shared_cstr(std::string const&); + + // Copy string as a unique_ptr to an array. + QPDF_DLL + std::unique_ptr make_unique_cstr(std::string const&); + + // Create a shared pointer to an array. From c++20, std::make_shared(n) does this. + template + std::shared_ptr + make_shared_array(size_t n) + { + return std::shared_ptr(new T[n], std::default_delete()); + } + + // Returns lower-case hex-encoded version of the string, treating each character in the input + // string as unsigned. The output string will be twice as long as the input string. + QPDF_DLL + std::string hex_encode(std::string const&); + + // Returns lower-case hex-encoded version of the char including a leading "#". + QPDF_DLL + std::string hex_encode_char(char); + + // Returns a string that is the result of decoding the input string. The input string may + // consist of mixed case hexadecimal digits. Any characters that are not hexadecimal digits will + // be silently ignored. If there are an odd number of hexadecimal digits, a trailing 0 will be + // assumed. + QPDF_DLL + std::string hex_decode(std::string const&); + + // Decode a single hex digit into a char in the range 0 <= char < 16. Return a char >= 16 if + // digit is not a valid hex digit. + QPDF_DLL + char hex_decode_char(char digit); + + // Set stdin, stdout to binary mode + QPDF_DLL + void binary_stdout(); + QPDF_DLL + void binary_stdin(); + // Set stdout to line buffered + QPDF_DLL + void setLineBuf(FILE*); + + // May modify argv0 + QPDF_DLL + char* getWhoami(char* argv0); + + // Get the value of an environment variable in a portable fashion. Returns true iff the variable + // is defined. If `value' is non-null, initializes it with the value of the variable. + QPDF_DLL + bool get_env(std::string const& var, std::string* value = nullptr); + + QPDF_DLL + time_t get_current_time(); + + // Portable structure representing a point in time with second granularity and time zone offset. + struct QPDFTime + { + QPDFTime() = default; + QPDFTime(QPDFTime const&) = default; + QPDFTime& operator=(QPDFTime const&) = default; + QPDFTime(int year, int month, int day, int hour, int minute, int second, int tz_delta) : + year(year), + month(month), + day(day), + hour(hour), + minute(minute), + second(second), + tz_delta(tz_delta) + { + } + int year; // actual year, no 1900 stuff + int month; // 1--12 + int day; // 1--31 + int hour; + int minute; + int second; + int tz_delta; // minutes before UTC + }; + + QPDF_DLL + QPDFTime get_current_qpdf_time(); + + // Convert a QPDFTime structure to a PDF timestamp string, which is "D:yyyymmddhhmmss" where + // is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone offset. may also be + // omitted. + // Examples: "D:20210207161528-05'00'", "D:20210207211528Z", "D:20210207211528". + // See get_current_qpdf_time and the QPDFTime structure above. + QPDF_DLL + std::string qpdf_time_to_pdf_time(QPDFTime const&); + + // Convert QPDFTime to a second-granularity ISO-8601 timestamp. + QPDF_DLL + std::string qpdf_time_to_iso8601(QPDFTime const&); + + // Convert a PDF timestamp string to a QPDFTime. If syntactically valid, return true and fill in + // qtm. If not valid, return false, and do not modify qtm. If qtm is null, just check the + // validity of the string. + QPDF_DLL + bool pdf_time_to_qpdf_time(std::string const&, QPDFTime* qtm = nullptr); + + // Convert PDF timestamp to a second-granularity ISO-8601 timestamp. If syntactically valid, + // return true and initialize iso8601. Otherwise, return false. + bool pdf_time_to_iso8601(std::string const& pdf_time, std::string& iso8601); + + // Return a string containing the byte representation of the UTF-8 encoding for the unicode + // value passed in. + QPDF_DLL + std::string toUTF8(unsigned long uval); + + // Return a string containing the byte representation of the UTF-16 big-endian encoding for the + // unicode value passed in. Unrepresentable code points are converted to U+FFFD. + QPDF_DLL + std::string toUTF16(unsigned long uval); + + // If utf8_val.at(pos) points to the beginning of a valid UTF-8-encoded character, return the + // codepoint of the character and set error to false. Otherwise, return 0xfffd and set error to + // true. In all cases, pos is advanced to the next position that may begin a valid character. + // When the string has been consumed, pos will be set to the string length. It is an error to + // pass a value of pos that is greater than or equal to the length of the string. + QPDF_DLL + unsigned long get_next_utf8_codepoint(std::string const& utf8_val, size_t& pos, bool& error); + + // Test whether this is a UTF-16 string. This is indicated by first two bytes being 0xFE 0xFF + // (big-endian) or 0xFF 0xFE (little-endian), each of which is the encoding of U+FEFF, the + // Unicode marker. Starting in qpdf 10.6.2, this detects little-endian as well as big-endian. + // Even though the PDF spec doesn't allow little-endian, most readers seem to accept it. + QPDF_DLL + bool is_utf16(std::string const&); + + // Test whether this is an explicit UTF-8 string as allowed by the PDF 2.0 spec. This is + // indicated by first three bytes being 0xEF 0xBB 0xBF, which is the UTF-8 encoding of U+FEFF. + QPDF_DLL + bool is_explicit_utf8(std::string const&); + + // Convert a UTF-8 encoded string to UTF-16 big-endian. Unrepresentable code points are + // converted to U+FFFD. + QPDF_DLL + std::string utf8_to_utf16(std::string const& utf8); + + // Convert a UTF-8 encoded string to the specified single-byte encoding system by replacing all + // unsupported characters with the given unknown_char. + QPDF_DLL + std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?'); + + // These versions return true if the conversion was successful and false if any unrepresentable + // characters were found and had to be substituted with the unknown character. + QPDF_DLL + bool utf8_to_ascii(std::string const& utf8, std::string& ascii, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_win_ansi(std::string const& utf8, std::string& win, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_mac_roman(std::string const& utf8, std::string& mac, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_pdf_doc(std::string const& utf8, std::string& pdfdoc, char unknown_char = '?'); + + // Convert a UTF-16 encoded string to UTF-8. Unrepresentable code + // points are converted to U+FFFD. + QPDF_DLL + std::string utf16_to_utf8(std::string const& utf16); + + // Convert from the specified single-byte encoding system to UTF-8. There is no ascii_to_utf8 + // because all ASCII strings are already valid UTF-8. + QPDF_DLL + std::string win_ansi_to_utf8(std::string const& win); + QPDF_DLL + std::string mac_roman_to_utf8(std::string const& mac); + QPDF_DLL + std::string pdf_doc_to_utf8(std::string const& pdfdoc); + + // Analyze a string for encoding. We can't tell the difference between any single-byte + // encodings, and we can't tell for sure whether a string that happens to be valid UTF-8 isn't a + // different encoding, but we can at least tell a few things to help us guess. If there are no + // characters with the high bit set, has_8bit_chars is false, and the other values are also + // false, even though ASCII strings are valid UTF-8. is_valid_utf8 means that the string is + // non-trivially valid UTF-8. Although the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and + // just about everything else) accepts UTF-16LE (as of 10.6.2). + QPDF_DLL + void analyze_encoding( + std::string const& str, bool& has_8bit_chars, bool& is_valid_utf8, bool& is_utf16); + + // Try to compensate for previously incorrectly encoded strings. We want to compensate for the + // following errors: + // + // * The string was supposed to be UTF-8 but was one of the single-byte encodings + // * The string was supposed to be PDF Doc but was either UTF-8 or one of the other single-byte + // encodings + // + // The returned vector always contains the original string first, and then it contains what the + // correct string would be in the event that the original string was the result of any of the + // above errors. + // + // This method is useful for attempting to recover a password that may have been previously + // incorrectly encoded. For example, the password was supposed to be UTF-8 but the previous + // application used a password encoded in WinAnsi, or if the previous password was supposed to + // be PDFDoc but was actually given as UTF-8 or WinAnsi, this method would find the correct + // password. + QPDF_DLL + std::vector possible_repaired_encodings(std::string); + + // Return a cryptographically secure random number. + QPDF_DLL + long random(); + + // Initialize a buffer with cryptographically secure random bytes. + QPDF_DLL + void initializeWithRandomBytes(unsigned char* data, size_t len); + + // Supply a random data provider. Starting in qpdf 10.0.0, qpdf uses the crypto provider as its + // source of random numbers. If you are using the native crypto provider, then qpdf will either + // use the operating system's secure random number source or, only if enabled at build time, an + // insecure random source from stdlib. The caller is responsible for managing the memory for the + // RandomDataProvider. This method modifies a static variable. If you are providing your own + // random data provider, you should call this at the beginning of your program before creating + // any QPDF objects. Passing a null to this method will reset the library back to its default + // random data provider. + QPDF_DLL + void setRandomDataProvider(RandomDataProvider*); + + // This returns the random data provider that would be used the next time qpdf needs random + // data. It will never return null. If no random data provider has been provided and the + // library was not compiled with any random data provider available, an exception will be + // thrown. + QPDF_DLL + RandomDataProvider* getRandomDataProvider(); + + // Filename is UTF-8 encoded, even on Windows, as described in the comments for safe_fopen. + QPDF_DLL + std::list read_lines_from_file(char const* filename, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(std::istream&, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(FILE*, bool preserve_eol = false); + QPDF_DLL + void read_lines_from_file( + std::function next_char, + std::list& lines, + bool preserve_eol = false); + + QPDF_DLL + void read_file_into_memory(char const* filename, std::shared_ptr& file_buf, size_t& size); + + QPDF_DLL + std::string read_file_into_string(char const* filename); + QPDF_DLL + std::string read_file_into_string(FILE* f, std::string_view filename = ""); + + // This used to be called strcasecmp, but that is a macro on some platforms, so we have to give + // it a name that is not likely to be a macro anywhere. + QPDF_DLL + int str_compare_nocase(char const*, char const*); + + // These routines help the tokenizer recognize certain character classes without using ctype, + // which we avoid because of locale considerations. + QPDF_DLL + bool is_hex_digit(char); + + QPDF_DLL + bool is_space(char); + + QPDF_DLL + bool is_digit(char); + + QPDF_DLL + bool is_number(char const*); + + /// @brief Handles the result code from qpdf functions. + /// + /// **For qpdf internal use only - not part of the public API** + /// @par + /// Depending on the result code, either continues execution or throws an + /// exception in case of an invalid parameter. + /// + /// @param result The result code of type qpdf_result_e, indicating success or failure status. + /// @param context A string describing the context where this function is invoked, used for + /// error reporting if an exception is thrown. + /// + /// @throws std::logic_error If the result code is `qpdf_bad_parameter`, indicating an invalid + /// parameter was supplied to a function. The exception message will + /// include the provided context for easier debugging. + /// + /// @since 12.3 + QPDF_DLL + void handle_result_code(qpdf_result_e result, std::string_view context); + + // This method parses the numeric range syntax used by the qpdf command-line tool. May throw + // std::runtime_error. A numeric range is as comma-separated list of groups. A group may be a + // number specification or a range of number specifications separated by a dash. A number + // specification may be one of the following (where is a number): + // * -- the numeric value of n + // * z -- the value of the `max` parameter + // * r -- represents max + 1 - ( from the end) + // + // If the group is two number specifications separated by a dash, it represents the range of + // numbers from the first to the second, inclusive. If the first is greater than the second, the + // numbers are descending. + // + // From qpdf 11.7.1: if a group starts with `x`, its members are excluded from the previous + // group that didn't start with `x1. + // + // Example: with max of 15, the range "4-10,x7-9,12-8,xr5" is 4, 5, 6, 10, 12, 10, 9, 8. This is + // 4 through 10 inclusive without 7 through 9 inclusive followed by 12 to 8 inclusive + // (descending) without 11 (the fifth value counting backwards from 15). For more information + // and additional examples, see the "Page Ranges" section in the manual. + QPDF_DLL + std::vector parse_numrange(char const* range, int max); + +#ifndef QPDF_NO_WCHAR_T + // If you are building qpdf on a stripped down system that doesn't have wchar_t, such as may be + // the case in some embedded environments, you may define QPDF_NO_WCHAR_T in your build. This + // symbol is never defined automatically. Search for wchar_t in qpdf's top-level README.md file + // for details. + + // Take an argv array consisting of wchar_t, as when wmain is invoked, convert all UTF-16 + // encoded strings to UTF-8, and call another main. + QPDF_DLL + int call_main_from_wmain(int argc, wchar_t* argv[], std::function realmain); + QPDF_DLL + int call_main_from_wmain( + int argc, + wchar_t const* const argv[], + std::function realmain); +#endif // QPDF_NO_WCHAR_T + + // Try to return the maximum amount of memory allocated by the current process and its threads. + // Return 0 if unable to determine. This is Linux-specific and not implemented to be completely + // reliable. It is used during development for performance testing to detect changes that may + // significantly change memory usage. It is not recommended for use for other purposes. + QPDF_DLL + size_t get_max_memory_usage(); +}; // namespace QUtil + +#endif // QUTIL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/RandomDataProvider.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/RandomDataProvider.hh new file mode 100644 index 0000000..c929f0f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/RandomDataProvider.hh @@ -0,0 +1,44 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef RANDOMDATAPROVIDER_HH +#define RANDOMDATAPROVIDER_HH + +#include +#include // for size_t + +class QPDF_DLL_CLASS RandomDataProvider +{ + public: + virtual ~RandomDataProvider() = default; + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + protected: + QPDF_DLL_PRIVATE + RandomDataProvider() = default; + + private: + RandomDataProvider(RandomDataProvider const&) = delete; + RandomDataProvider& operator=(RandomDataProvider const&) = delete; +}; + +#endif // RANDOMDATAPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Types.h b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Types.h new file mode 100644 index 0000000..015cd22 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/Types.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFTYPES_H +#define QPDFTYPES_H + +/* Provide an offset type that should be as big as off_t on just about + * any system. If your compiler doesn't support C99 (or at least the + * "long long" type), then you may have to modify this definition. + */ + +typedef long long int qpdf_offset_t; + +#endif /* QPDFTYPES_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_att.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_att.hh new file mode 100644 index 0000000..ea85419 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_att.hh @@ -0,0 +1,14 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL AttConfig* replace(); +QPDF_DLL AttConfig* key(std::string const& parameter); +QPDF_DLL AttConfig* filename(std::string const& parameter); +QPDF_DLL AttConfig* creationdate(std::string const& parameter); +QPDF_DLL AttConfig* moddate(std::string const& parameter); +QPDF_DLL AttConfig* mimetype(std::string const& parameter); +QPDF_DLL AttConfig* description(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_copy_att.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_copy_att.hh new file mode 100644 index 0000000..764a5ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_copy_att.hh @@ -0,0 +1,9 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL CopyAttConfig* prefix(std::string const& parameter); +QPDF_DLL CopyAttConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_enc.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_enc.hh new file mode 100644 index 0000000..ed4d071 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_enc.hh @@ -0,0 +1,20 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL EncConfig* extract(std::string const& parameter); +QPDF_DLL EncConfig* annotate(std::string const& parameter); +QPDF_DLL EncConfig* print(std::string const& parameter); +QPDF_DLL EncConfig* modify(std::string const& parameter); +QPDF_DLL EncConfig* cleartextMetadata(); +QPDF_DLL EncConfig* forceV4(); +QPDF_DLL EncConfig* accessibility(std::string const& parameter); +QPDF_DLL EncConfig* assemble(std::string const& parameter); +QPDF_DLL EncConfig* form(std::string const& parameter); +QPDF_DLL EncConfig* modifyOther(std::string const& parameter); +QPDF_DLL EncConfig* useAes(std::string const& parameter); +QPDF_DLL EncConfig* forceR5(); +QPDF_DLL EncConfig* allowInsecure(); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_global.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_global.hh new file mode 100644 index 0000000..7f8758b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_global.hh @@ -0,0 +1,13 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL GlobalConfig* noDefaultLimits(); +QPDF_DLL GlobalConfig* parserMaxContainerSize(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxContainerSizeDamaged(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxErrors(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxNesting(std::string const& parameter); +QPDF_DLL GlobalConfig* maxStreamFilters(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_limits.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_limits.hh new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_main.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_main.hh new file mode 100644 index 0000000..0ed4f64 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_main.hh @@ -0,0 +1,97 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL Config* allowWeakCrypto(); +QPDF_DLL Config* check(); +QPDF_DLL Config* checkLinearization(); +QPDF_DLL Config* coalesceContents(); +QPDF_DLL Config* decrypt(); +QPDF_DLL Config* deterministicId(); +QPDF_DLL Config* externalizeInlineImages(); +QPDF_DLL Config* filteredStreamData(); +QPDF_DLL Config* flattenRotation(); +QPDF_DLL Config* generateAppearances(); +QPDF_DLL Config* ignoreXrefStreams(); +QPDF_DLL Config* isEncrypted(); +QPDF_DLL Config* jsonInput(); +QPDF_DLL Config* keepInlineImages(); +QPDF_DLL Config* linearize(); +QPDF_DLL Config* listAttachments(); +QPDF_DLL Config* newlineBeforeEndstream(); +QPDF_DLL Config* noOriginalObjectIds(); +QPDF_DLL Config* noWarn(); +QPDF_DLL Config* optimizeImages(); +QPDF_DLL Config* passwordIsHexKey(); +QPDF_DLL Config* preserveUnreferenced(); +QPDF_DLL Config* preserveUnreferencedResources(); +QPDF_DLL Config* progress(); +QPDF_DLL Config* qdf(); +QPDF_DLL Config* rawStreamData(); +QPDF_DLL Config* recompressFlate(); +QPDF_DLL Config* removeAcroform(); +QPDF_DLL Config* removeInfo(); +QPDF_DLL Config* removeMetadata(); +QPDF_DLL Config* removePageLabels(); +QPDF_DLL Config* removeStructure(); +QPDF_DLL Config* reportMemoryUsage(); +QPDF_DLL Config* requiresPassword(); +QPDF_DLL Config* removeRestrictions(); +QPDF_DLL Config* showEncryption(); +QPDF_DLL Config* showEncryptionKey(); +QPDF_DLL Config* showLinearization(); +QPDF_DLL Config* showNpages(); +QPDF_DLL Config* showPages(); +QPDF_DLL Config* showXref(); +QPDF_DLL Config* staticAesIv(); +QPDF_DLL Config* staticId(); +QPDF_DLL Config* suppressPasswordRecovery(); +QPDF_DLL Config* suppressRecovery(); +QPDF_DLL Config* testJsonSchema(); +QPDF_DLL Config* verbose(); +QPDF_DLL Config* warningExit0(); +QPDF_DLL Config* withImages(); +QPDF_DLL Config* compressionLevel(std::string const& parameter); +QPDF_DLL Config* jpegQuality(std::string const& parameter); +QPDF_DLL Config* copyEncryption(std::string const& parameter); +QPDF_DLL Config* encryptionFilePassword(std::string const& parameter); +QPDF_DLL Config* forceVersion(std::string const& parameter); +QPDF_DLL Config* iiMinBytes(std::string const& parameter); +QPDF_DLL Config* jobJsonFile(std::string const& parameter); +QPDF_DLL Config* jsonObject(std::string const& parameter); +QPDF_DLL Config* keepFilesOpenThreshold(std::string const& parameter); +QPDF_DLL Config* linearizePass1(std::string const& parameter); +QPDF_DLL Config* minVersion(std::string const& parameter); +QPDF_DLL Config* oiMinArea(std::string const& parameter); +QPDF_DLL Config* oiMinHeight(std::string const& parameter); +QPDF_DLL Config* oiMinWidth(std::string const& parameter); +QPDF_DLL Config* password(std::string const& parameter); +QPDF_DLL Config* passwordFile(std::string const& parameter); +QPDF_DLL Config* removeAttachment(std::string const& parameter); +QPDF_DLL Config* rotate(std::string const& parameter); +QPDF_DLL Config* showAttachment(std::string const& parameter); +QPDF_DLL Config* showObject(std::string const& parameter); +QPDF_DLL Config* jsonStreamPrefix(std::string const& parameter); +QPDF_DLL Config* updateFromJson(std::string const& parameter); +QPDF_DLL Config* collate(std::string const& parameter); +QPDF_DLL Config* collate(); +QPDF_DLL Config* splitPages(std::string const& parameter); +QPDF_DLL Config* splitPages(); +QPDF_DLL Config* compressStreams(std::string const& parameter); +QPDF_DLL Config* decodeLevel(std::string const& parameter); +QPDF_DLL Config* flattenAnnotations(std::string const& parameter); +QPDF_DLL Config* jsonKey(std::string const& parameter); +QPDF_DLL Config* jsonStreamData(std::string const& parameter); +QPDF_DLL Config* keepFilesOpen(std::string const& parameter); +QPDF_DLL Config* normalizeContent(std::string const& parameter); +QPDF_DLL Config* objectStreams(std::string const& parameter); +QPDF_DLL Config* passwordMode(std::string const& parameter); +QPDF_DLL Config* removeUnreferencedResources(std::string const& parameter); +QPDF_DLL Config* streamData(std::string const& parameter); +QPDF_DLL Config* json(std::string const& parameter); +QPDF_DLL Config* json(); +QPDF_DLL Config* jsonOutput(std::string const& parameter); +QPDF_DLL Config* jsonOutput(); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_pages.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_pages.hh new file mode 100644 index 0000000..75b0ae5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_pages.hh @@ -0,0 +1,10 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL PagesConfig* file(std::string const& parameter); +QPDF_DLL PagesConfig* range(std::string const& parameter); +QPDF_DLL PagesConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_set_page_labels.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_set_page_labels.hh new file mode 100644 index 0000000..b816d29 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_set_page_labels.hh @@ -0,0 +1,7 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_uo.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_uo.hh new file mode 100644 index 0000000..547ecf3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/auto_job_c_uo.hh @@ -0,0 +1,12 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL UOConfig* file(std::string const& parameter); +QPDF_DLL UOConfig* to(std::string const& parameter); +QPDF_DLL UOConfig* from(std::string const& parameter); +QPDF_DLL UOConfig* repeat(std::string const& parameter); +QPDF_DLL UOConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/global.hh b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/global.hh new file mode 100644 index 0000000..b99ee31 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/global.hh @@ -0,0 +1,264 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef GLOBAL_HH +#define GLOBAL_HH + +#include + +#include +#include + +#include + +namespace qpdf::global +{ + /// Helper function to translate result codes into C++ exceptions - for qpdf internal use only. + inline void + handle_result(qpdf_result_e result) + { + if (result != qpdf_r_ok) { + QUtil::handle_result_code(result, "qpdf::global"); + } + } + + /// Helper function to wrap calls to qpdf_global_get_uint32 - for qpdf internal use only. + inline uint32_t + get_uint32(qpdf_param_e param) + { + uint32_t value; + handle_result(qpdf_global_get_uint32(param, &value)); + return value; + } + + /// Helper function to wrap calls to qpdf_global_set_uint32 - for qpdf internal use only. + inline void + set_uint32(qpdf_param_e param, uint32_t value) + { + handle_result(qpdf_global_set_uint32(param, value)); + } + + /// @brief Retrieves the number of limit errors. + /// + /// Returns the number of times a global limit was exceeded. This item is read only. + /// + /// @return The number of limit errors. + /// + /// @since 12.3 + uint32_t inline limit_errors() + { + return get_uint32(qpdf_p_limit_errors); + } + + namespace options + { + /// @brief Retrieves whether inspection mode is set. + /// + /// @return True if inspection mode is set. + /// + /// @since 12.3 + bool inline inspection_mode() + { + return get_uint32(qpdf_p_inspection_mode) != 0; + } + + /// @brief Set inspection mode if `true` is passed. + /// + /// This function enables restrictive inspection mode if `true` is passed. Inspection mode + /// must be enabled before a QPDF object is created. By default inspection mode is off. + /// Calling `inspection_mode(false)` is not supported and currently is a no-op. + /// + /// @param value A boolean indicating whether to enable (true) inspection mode. + /// + /// @since 12.3 + void inline inspection_mode(bool value) + { + set_uint32(qpdf_p_inspection_mode, value ? QPDF_TRUE : QPDF_FALSE); + } + + /// @brief Retrieves whether default limits are enabled. + /// + /// @return True if default limits are enabled. + /// + /// @since 12.3 + bool inline default_limits() + { + return get_uint32(qpdf_p_default_limits) != 0; + } + + /// @brief Disable all optional default limits if `false` is passed. + /// + /// This function disables all optional default limits if `false` is passed. Once default + /// values have been disabled they cannot be re-enabled. Passing `true` has no effect. This + /// function will leave any limits that have been explicitly set unchanged. Some limits, + /// such as limits imposed to avoid stack overflows, cannot be disabled but can be changed. + /// + /// @param value A boolean indicating whether to disable (false) the default limits. + /// + /// @since 12.3 + void inline default_limits(bool value) + { + set_uint32(qpdf_p_default_limits, value ? QPDF_TRUE : QPDF_FALSE); + } + + } // namespace options + + namespace limits + { + /// @brief Retrieves the maximum nesting level while parsing objects. + /// + /// @return The maximum nesting level while parsing objects. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + uint32_t inline parser_max_nesting() + { + return get_uint32(qpdf_p_parser_max_nesting); + } + + /// @brief Sets the maximum nesting level while parsing objects. + /// + /// @param value The maximum nesting level to set. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + void inline parser_max_nesting(uint32_t value) + { + set_uint32(qpdf_p_parser_max_nesting, value); + } + + /// @brief Retrieves the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @return The maximum number of errors allowed while parsing objects. + /// + /// @since 12.3 + uint32_t inline parser_max_errors() + { + return get_uint32(qpdf_p_parser_max_errors); + } + + /// Sets the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @param value The maximum number of errors allowed while parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_errors(uint32_t value) + { + set_uint32(qpdf_p_parser_max_errors, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size() + { + return get_uint32(qpdf_p_parser_max_container_size); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing objects. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing xref streams. The default limit is 5,000. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size_damaged() + { + return get_uint32(qpdf_p_parser_max_container_size_damaged); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing trailer dictionaries and xref streams. The + /// default limit is 5,000. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size_damaged(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size_damaged, value); + } + + /// @brief Retrieves the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @return The maximum number of filters allowed when filtering streams. + /// + /// @since 12.3 + uint32_t inline max_stream_filters() + { + return get_uint32(qpdf_p_max_stream_filters); + } + + /// @brief Sets the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @param value The maximum number of filters allowed when filtering streams to set. + /// + /// @since 12.3 + void inline max_stream_filters(uint32_t value) + { + set_uint32(qpdf_p_max_stream_filters, value); + } + } // namespace limits + +} // namespace qpdf::global + +#endif // GLOBAL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdf-c.h b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdf-c.h new file mode 100644 index 0000000..c602f9f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdf-c.h @@ -0,0 +1,1070 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDF_C_H +#define QPDF_C_H + +/* + * This file defines a basic "C" API for qpdf. It provides access to a subset of the QPDF library's + * capabilities to make them accessible to callers who can't handle calling C++ functions or working + * with C++ classes. This may be especially useful to Windows users who are accessing the qpdf DLL + * directly or to other people programming in non-C/C++ languages that can call C code but not C++ + * code. Starting with qpdf 11.7, it is possible to write your own `extern "C"` functions that + * interoperate with the C API. + * + * There are several things to keep in mind when using the C API. + * + * Error handling is tricky because the underlying C++ API uses exception handling. See "ERROR + * HANDLING" below for a detailed explanation. + * + * The C API is not as rich as the C++ API. For many operations, you must use the C++ API. The C + * API is primarily useful for doing basic transformations on PDF files similar to what you + * might do with the qpdf command-line tool. You can write your own `extern "C"` functions in + * C++ that interoperate with the C API by using qpdf_c_get_qpdf and qpdf_c_wrap which were + * introduced in qpdf 11.7.0. + * + * These functions store their state in a qpdf_data object. Individual instances of qpdf_data + * are not thread-safe: although you may access different qpdf_data objects from different + * threads, you may not access one qpdf_data simultaneously from multiple threads. + * + * All dynamic memory, except for that of the qpdf_data object itself, is managed by the library + * unless otherwise noted. You must create a qpdf_data object using qpdf_init and free it using + * qpdf_cleanup. + * + * Many functions return char*. In all cases, the char* values returned are pointers to data + * inside the qpdf_data object. As such, they are always freed by qpdf_cleanup. In most cases, + * strings returned by functions here may be invalidated by subsequent function calls, sometimes + * even to different functions. If you want a string to last past the next qpdf call or after a + * call to qpdf_cleanup, you should make a copy of it. + * + * Since it is possible for a PDF string to contain null characters, a function that returns + * data originating from a PDF string may also contain null characters. To handle that case, you + * call qpdf_get_last_string_length() to get the length of whatever string was just returned. + * See STRING FUNCTIONS below. + * + * Most functions defined here have obvious counterparts that are methods to either QPDF or + * QPDFWriter. Please see comments in QPDF.hh and QPDFWriter.hh for details on their use. In + * order to avoid duplication of information, comments here focus primarily on differences + * between the C and C++ API. + */ + +/* ERROR HANDLING -- changed in qpdf 10.5 */ + +/* SUMMARY: The only way to know whether a function that does not return an error code has + * encountered an error is to call qpdf_has_error after each function. You can do this even for + * functions that do return error codes. You can also call qpdf_silence_errors to prevent qpdf from + * writing these errors to stderr. + * + * DETAILS: + * + * The data type underlying qpdf_data maintains a list of warnings and a single error. To retrieve + * warnings, call qpdf_next_warning while qpdf_more_warnings is true. To retrieve the error, call + * qpdf_get_error when qpdf_has_error is true. + * + * There are several things that are important to understand. + * + * Some functions return an error code. The value of the error code is made up of a bitwise-OR of + * QPDF_WARNINGS and QPDF_ERRORS. The QPDF_ERRORS bit is set if there was an error during the *most + * recent call* to the API. The QPDF_WARNINGS bit is set if there are any warnings that have not yet + * been retrieved by calling qpdf_more_warnings. It is possible for both its or neither bit to be + * set. + * + * The expected mode of operation is to go through a series of operations, checking for errors after + * each call, but only checking for warnings at the end. This is similar to how it works in the C++ + * API where warnings are handled in exactly this way but errors result in exceptions being thrown. + * However, in both the C and C++ API, it is possible to check for and handle warnings as they + * arise. + * + * Some functions return values (or void) rather than an error code. This is especially true with + * the object handling functions. Those functions can still generate errors. To handle errors in + * those cases, you should explicitly call qpdf_has_error(). Note that, if you want to avoid the + * inconsistencies in the interface, you can always check for error conditions in this way rather + * than looking at status return codes. + * + * Prior to qpdf 10.5, if one of the functions that does not return an error code encountered an + * exception, it would cause the entire program to crash. Starting in qpdf 10.5, the default + * response to an error condition in these situations is to print the error to standard error, issue + * exactly one warning indicating that such an error occurred, and return a sensible fallback value + * (0 for numbers, QPDF_FALSE for booleans, "" for strings, or a null or uninitialized object + * handle). This is better than the old behavior but still undesirable as the best option is to + * explicitly check for error conditions. + * + * To prevent qpdf from writing error messages to stderr in this way, you can call + * qpdf_silence_errors(). This signals to the qpdf library that you intend to check the error codes + * yourself. + * + * If you encounter a situation where an exception from the C++ code is not properly converted to an + * error as described above, it is a bug in qpdf, which should be reported at + * https://github.com/qpdf/qpdf/issues/new. + */ + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _qpdf_data* qpdf_data; + typedef struct _qpdf_error* qpdf_error; + + /* Many functions return an integer error code. Codes are defined below. See comments at the + * top of the file for details. Note that the values below can be logically orred together. + */ + typedef int QPDF_ERROR_CODE; +#define QPDF_SUCCESS 0 +#define QPDF_WARNINGS 1 << 0 +#define QPDF_ERRORS 1 << 1 + + typedef int QPDF_BOOL; +#define QPDF_TRUE 1 +#define QPDF_FALSE 0 + + /* From qpdf 10.5: call this method to signal to the library that you are explicitly handling + * errors from functions that don't return error codes. Otherwise, the library will print these + * error conditions to stderr and issue a warning. Prior to 10.5, the program would have + * crashed from an unhandled exception. + */ + QPDF_DLL + void qpdf_silence_errors(qpdf_data qpdf); + + /* Returns the version of the qpdf software. This is guaranteed to be a static value. + */ + QPDF_DLL + char const* qpdf_get_qpdf_version(); + + /* Returns dynamically allocated qpdf_data pointer; must be freed by calling qpdf_cleanup. You + * must call qpdf_read, one of the other qpdf_read_* functions, or qpdf_empty_pdf before calling + * any function that would need to operate on the PDF file. + */ + QPDF_DLL + qpdf_data qpdf_init(); + + /* Pass a pointer to the qpdf_data pointer created by qpdf_init to clean up resources. This does + * not include buffers initialized by functions that return stream data but it otherwise + * includes all data associated with the QPDF object or any object handles. + */ + QPDF_DLL + void qpdf_cleanup(qpdf_data* qpdf); + + /* ERROR REPORTING */ + + /* Returns 1 if there is an error condition. The error condition can be retrieved by a single + * call to qpdf_get_error. + */ + QPDF_DLL + QPDF_BOOL qpdf_has_error(qpdf_data qpdf); + + /* Returns the error condition, if any. The return value is a pointer to data that will become + * invalid after the next call to this function, qpdf_next_warning, or qpdf_cleanup. After this + * function is called, qpdf_has_error will return QPDF_FALSE until the next error condition + * occurs. If there is no error condition, this function returns a null pointer. + */ + QPDF_DLL + qpdf_error qpdf_get_error(qpdf_data qpdf); + + /* Returns 1 if there are any unretrieved warnings, and zero otherwise. + */ + QPDF_DLL + QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf); + + /* If there are any warnings, returns a pointer to the next warning. Otherwise returns a null + * pointer. + */ + QPDF_DLL + qpdf_error qpdf_next_warning(qpdf_data qpdf); + + /* Extract fields of the error. */ + + /* Use this function to get a full error message suitable for showing to the user. */ + QPDF_DLL + char const* qpdf_get_error_full_text(qpdf_data q, qpdf_error e); + + /* Use these functions to extract individual fields from the error; see QPDFExc.hh for details. + */ + QPDF_DLL + enum qpdf_error_code_e qpdf_get_error_code(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_filename(qpdf_data q, qpdf_error e); + QPDF_DLL + unsigned long long qpdf_get_error_file_position(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_message_detail(qpdf_data q, qpdf_error e); + + /* By default, warnings are written to stderr. Passing true to this function will prevent + * warnings from being written to stderr. They will still be available by calls to + * qpdf_next_warning. + */ + QPDF_DLL + void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value); + + /* LOG FUNCTIONS */ + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdf_set_logger(qpdf_data qpdf, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdf_get_logger(qpdf_data qpdf); + + /* CHECK FUNCTIONS */ + + /* Attempt to read the entire PDF file to see if there are any errors qpdf can detect. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf); + + /* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */ + + QPDF_DLL + void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value); + + /* PROCESS FUNCTIONS */ + + /* This functions process a PDF or JSON input source. */ + + /* Calling qpdf_read causes processFile to be called in the C++ API. Basic parsing is + * performed, but data from the file is only read as needed. For files without passwords, pass + * a null pointer or an empty string as the password. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_read(qpdf_data qpdf, char const* filename, char const* password); + + /* Calling qpdf_read_memory causes processMemoryFile to be called in the C++ API. Otherwise, it + * behaves in the same way as qpdf_read. The description argument will be used in place of the + * file name in any error or warning messages generated by the library. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_read_memory( + qpdf_data qpdf, + char const* description, + char const* buffer, + unsigned long long size, + char const* password); + + /* Calling qpdf_empty_pdf initializes this qpdf object with an empty PDF, making it possible to + * create a PDF from scratch using the C API. Added in 10.6. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf); + + /* Create a PDF from a JSON file. This calls createFromJSON in the C++ API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_file(qpdf_data qpdf, char const* filename); + + /* Create a PDF from JSON data in a null-terminated string. This calls createFromJSON in the C++ + * API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* JSON UPDATE FUNCTIONS */ + + /* Update a QPDF object from a JSON file or buffer. These functions call updateFromJSON. One of + * the other processing functions has to be called first so that the QPDF object is initialized + * with PDF data. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_file(qpdf_data qpdf, char const* filename); + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* READ FUNCTIONS */ + + /* Read functions below must be called after qpdf_read or any of the other functions that + * process a PDF. */ + + /* + * NOTE: Functions that return char* are returning a pointer to an internal buffer that will be + * reused for each call to a function that returns a char*. You must use or copy the value + * before calling any other qpdf library functions. + */ + + /* Return the version of the PDF file. See warning above about functions that return char*. */ + QPDF_DLL + char const* qpdf_get_pdf_version(qpdf_data qpdf); + + /* Return the extension level of the PDF file. */ + QPDF_DLL + int qpdf_get_pdf_extension_level(qpdf_data qpdf); + + /* Return the user password. If the file is opened using the owner password, the user password + * may be retrieved using this function. If the file is opened using the user password, this + * function will return that user password. See warning above about functions that return + * char*. + */ + QPDF_DLL + char const* qpdf_get_user_password(qpdf_data qpdf); + + /* Return the string value of a key in the document's Info dictionary. The key parameter should + * include the leading slash, e.g. "/Author". If the key is not present or has a non-string + * value, a null pointer is returned. Otherwise, a pointer to an internal buffer is returned. + * See warning above about functions that return char*. + */ + QPDF_DLL + char const* qpdf_get_info_key(qpdf_data qpdf, char const* key); + + /* Set a value in the info dictionary, possibly replacing an existing value. The key must + * include the leading slash (e.g. "/Author"). Passing a null pointer as a value will remove + * the key from the info dictionary. Otherwise, a copy will be made of the string that is + * passed in. + */ + QPDF_DLL + void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value); + + /* Indicate whether the input file is linearized. */ + QPDF_DLL + QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf); + + /* Indicate whether the input file is encrypted. */ + QPDF_DLL + QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf); + + QPDF_DLL + QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf); + + /* JSON WRITE FUNCTIONS */ + + /* This function serializes the PDF to JSON. This calls writeJSON from the C++ API. + * + * - version: the JSON version, currently must be 2 + * - fn: a function that will be called with blocks of JSON data; will be called with data, a + * length, and the value of the udata parameter to this function + * - udata: will be passed as the third argument to fn with each call; use this for your own + * tracking or pass a null pointer if you don't need it + * - For decode_level, json_stream_data, file_prefix, and wanted_objects, see comments in + * QPDF.hh. For this API, wanted_objects should be a null-terminated array of null-terminated + * strings. Pass a null pointer if you want all objects. + */ + + /* Function should return 0 on success. */ + typedef int (*qpdf_write_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + QPDF_ERROR_CODE qpdf_write_json( + qpdf_data qpdf, + int version, + qpdf_write_fn_t fn, + void* udata, + enum qpdf_stream_decode_level_e decode_level, + enum qpdf_json_stream_data_e json_stream_data, + char const* file_prefix, + char const* const* wanted_objects); + + /* WRITE FUNCTIONS */ + + /* Set up for writing. No writing is actually performed until the call to qpdf_write(). + */ + + /* Supply the name of the file to be written and initialize the qpdf_data object to handle + * writing operations. This function also attempts to create the file. The PDF data is not + * written until the call to qpdf_write. qpdf_init_write may be called multiple times for the + * same qpdf_data object. When qpdf_init_write is called, all information from previous calls + * to functions that set write parameters (qpdf_set_linearization, etc.) is lost, so any write + * parameter functions must be called again. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename); + + /* Initialize for writing but indicate that the PDF file should be written to memory. Call + * qpdf_get_buffer_length and qpdf_get_buffer to retrieve the resulting buffer. The memory + * containing the PDF file will be destroyed when qpdf_cleanup is called. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf); + + /* Retrieve the buffer used if the file was written to memory. qpdf_get_buffer returns a null + * pointer if data was not written to memory. The memory is freed when qpdf_cleanup is called + * or if a subsequent call to qpdf_init_write or qpdf_init_write_memory is called. */ + QPDF_DLL + size_t qpdf_get_buffer_length(qpdf_data qpdf); + QPDF_DLL + unsigned char const* qpdf_get_buffer(qpdf_data qpdf); + + QPDF_DLL + void qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode); + + QPDF_DLL + void qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode); + + QPDF_DLL + void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_decode_level(qpdf_data qpdf, enum qpdf_stream_decode_level_e level); + + QPDF_DLL + void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_ID except in test suites to suppress generation of a random /ID. + * See also qpdf_set_deterministic_ID. + */ + QPDF_DLL + void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_aes_IV except in test suites to create predictable AES encrypted + * output. + */ + QPDF_DLL + void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_suppress_original_object_IDs(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value); + + /* The *_insecure functions are identical to the old versions but have been renamed as a an + * alert to the caller that they are insecure. See "Weak Cryptographic" in the manual for + * details. + */ + QPDF_DLL + void qpdf_set_r2_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_print, + QPDF_BOOL allow_modify, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_annotate); + + QPDF_DLL + void qpdf_set_r3_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print); + + QPDF_DLL + void qpdf_set_r4_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata, + QPDF_BOOL use_aes); + + QPDF_DLL + void qpdf_set_r5_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_r6_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void qpdf_set_minimum_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level); + + QPDF_DLL + void qpdf_force_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void + qpdf_force_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level); + + /* During write, your report_progress function will be called with a value between 0 and 100 + * representing the approximate write progress. The data object you pass to + * qpdf_register_progress_reporter will be handed back to your function. This function must be + * called after qpdf_init_write (or qpdf_init_write_memory) and before qpdf_write. The + * registered progress reporter applies only to a single write, so you must call it again if you + * perform a subsequent write with a new writer. + */ + QPDF_DLL + void qpdf_register_progress_reporter( + qpdf_data qpdf, void (*report_progress)(int percent, void* data), void* data); + + /* Do actual write operation. */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf); + + /* Object handling. + * + * These functions take and return a qpdf_oh object handle, which is just an unsigned integer. + * The value 0 is never returned, which makes it usable as an uninitialized value. The handles + * returned by these functions are guaranteed to be unique, i.e. two calls to (the same of + * different) functions will return distinct handles even when they refer to the same object. + * + * Each function below, starting with qpdf_oh, corresponds to a specific method of + * QPDFObjectHandler. For example, qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If + * the C++ method is overloaded, the C function's name will be disambiguated. If the C++ method + * takes optional arguments, the C function will have required arguments in those positions. For + * details about the method, please see comments in QPDFObjectHandle.hh. Comments here only + * explain things that are specific to the "C" API. + * + * Only a fraction of the methods of QPDFObjectHandle are available here. Most of the basic + * methods for creating, accessing, and modifying most types of objects are present. Most of the + * higher-level functions are not implemented. Functions for dealing with content streams as + * well as objects that only exist in content streams (operators and inline images) are mostly + * not provided. + * + * To refer to a specific QPDFObjectHandle, you need a pair consisting of a qpdf_data and a + * qpdf_oh, which is just an index into an internal table of objects. All memory allocated by + * any of these functions is returned when qpdf_cleanup is called. + * + * Regarding memory, the same rules apply as the above functions. Specifically, if a function + * returns a char*, the memory is managed by the library and, unless otherwise specified, is not + * expected to be valid after the next qpdf call. + * + * The qpdf_data object keeps a cache of handles returned by these functions. Once you are + * finished referencing a handle, you can optionally release it. Releasing handles is optional + * since they will all get released by qpdf_cleanup, but it can help to reduce the memory + * footprint of the qpdf_data object to release them when you're done. Releasing a handle does + * not destroy the object. All QPDFObjectHandle objects are deleted when they are no longer + * referenced. Releasing an object handle simply invalidates it. For example, if you create an + * object, add it to an existing dictionary or array, and then release its handle, the object is + * safely part of the dictionary or array. Similarly, any other object handle referring to the + * object remains valid. Explicitly releasing an object handle is essentially the same as + * letting a QPDFObjectHandle go out of scope in the C++ API. + * + * Please see "ERROR HANDLING" above for details on how error conditions are handled. + */ + + /* For examples of using this API, see examples/pdf-c-objects.c */ + + typedef unsigned int qpdf_oh; + + /* Releasing objects -- see comments above. These functions have no equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_oh_release_all(qpdf_data qpdf); + + /* Clone an object handle */ + QPDF_DLL + qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh); + + /* Get trailer and root objects */ + QPDF_DLL + qpdf_oh qpdf_get_trailer(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_get_root(qpdf_data qpdf); + + /* Retrieve and replace indirect objects */ + QPDF_DLL + qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh); + + /* Wrappers around QPDFObjectHandle methods. Be sure to read corresponding comments in + * QPDFObjectHandle.hh to understand what each function does and what kinds of objects it + * applies to. Note that names are to appear in a canonicalized form starting with a leading + * slash and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle.hh + * for details. + */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary_of_type( + qpdf_data qpdf, qpdf_oh oh, char const* type, char const* subtype); + + QPDF_DLL + enum qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str); + + QPDF_DLL + QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value); + + QPDF_DLL + long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value); + QPDF_DLL + int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value); + QPDF_DLL + unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value); + QPDF_DLL + unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value); + + QPDF_DLL + char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value); + + QPDF_DLL + char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + /* Return the length of the last string returned. This enables you to retrieve the entire string + * for cases in which a char* returned by one of the functions below points to a string with + * embedded null characters. The function qpdf_oh_get_binary_string_value takes a length + * pointer, which can be useful if you are retrieving the value of a string that is expected to + * contain binary data, such as a checksum or document ID. It is always valid to call + * qpdf_get_last_string_length, but it is usually not necessary as C strings returned by the + * library are only expected to be able to contain null characters if their values originate + * from PDF strings in the input. + */ + QPDF_DLL + size_t qpdf_get_last_string_length(qpdf_data qpdf); + + QPDF_DLL + char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + + QPDF_DLL + int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n); + + /* In all dictionary APIs, keys are specified/represented as canonicalized name strings starting + * with / and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle for + * details. + */ + + /* "C"-specific dictionary key iteration */ + + /* Iteration is allowed on only one dictionary at a time. */ + QPDF_DLL + void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh dict); + QPDF_DLL + QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf); + /* The memory returned by qpdf_oh_dict_next_key is owned by qpdf_data. It is good until the next + * call to qpdf_oh_dict_next_key with the same qpdf_data object. Calling the function again, + * even with a different dict, invalidates previous return values. + */ + QPDF_DLL + char const* qpdf_oh_dict_next_key(qpdf_data qpdf); + + /* end "C"-specific dictionary key iteration */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_null(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value); + QPDF_DLL + qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf, double value, int decimal_places); + QPDF_DLL + qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name); + QPDF_DLL + qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str); + QPDF_DLL + qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str); + /* Use qpdf_oh_new_binary_string for creating a string that may contain arbitrary binary data + * including embedded null characters. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_array(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf); + + /* Create a new stream. Use qpdf_oh_get_dict to get (and subsequently modify) the stream + * dictionary if needed. See comments in QPDFObjectHandle.hh for newStream() for additional + * notes. You must call qpdf_oh_replace_stream_data to provide data for the stream. See STREAM + * FUNCTIONS below. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf); + + QPDF_DLL + void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item); + QPDF_DLL + void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at); + + QPDF_DLL + void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + QPDF_DLL + void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + + QPDF_DLL + qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh); + + /* Note about foreign objects: the C API does not have enough information in the value of a + * qpdf_oh to know what QPDF object it belongs to. To uniquely specify a qpdf object handle from + * a specific qpdf_data instance, you always pair the qpdf_oh with the correct qpdf_data. + * Otherwise, you are likely to get completely the wrong object if you are not lucky enough to + * get an error about the object being invalid. + */ + + /* Copy foreign object: the qpdf_oh returned belongs to `qpdf`, while `foreign_oh` belongs to + * `other_qpdf`. + */ + QPDF_DLL + qpdf_oh qpdf_oh_copy_foreign_object(qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh); + + /* STREAM FUNCTIONS */ + + /* These functions provide basic access to streams and stream data. They are not as + * comprehensive as what is in QPDFObjectHandle, but they do allow for working with streams and + * stream data as caller-managed memory. + */ + + /* Get stream data as a buffer. The buffer is allocated with malloc and must be freed by the + * caller. The size of the buffer is stored in *len. The arguments are similar to those in + * QPDFObjectHandle::pipeStreamData. To get raw stream data, pass qpdf_dl_none as decode_level. + * Otherwise, filtering is attempted and *filtered is set to indicate whether it was successful. + * If *filtered is QPDF_FALSE, then raw, unfiltered stream data was returned. You may pass a + * null pointer as filtered if you don't care about the result. If you pass a null pointer as + * bufp (and len), the value of filtered will be set to whether the stream can be filterable. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + enum qpdf_stream_decode_level_e decode_level, + QPDF_BOOL* filtered, + unsigned char** bufp, + size_t* len); + + /* This function returns the concatenation of all of a page's content streams as a single, + * dynamically allocated buffer. As with qpdf_oh_get_stream_data, the buffer is allocated with + * malloc and must be freed by the caller. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_page_content_data( + qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len); + + /* Call free to release a buffer allocated with malloc. This function can be used to free + * buffers that were dynamically allocated by qpdf functions such as qpdf_oh_get_stream_data or + * qpdf_oh_get_page_content_data. The caller is responsible for calling qpdf_oh_free_buffer (or + * calling free directly) to manage memory properly and avoid memory leaks. This function has no + * equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_free_buffer(unsigned char** bufp); + + /* The data pointed to by bufp will be copied by the library. It does not need to remain valid + * after the call returns. + */ + QPDF_DLL + void qpdf_oh_replace_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + unsigned char const* buf, + size_t len, + qpdf_oh filter, + qpdf_oh decode_parms); + + /* PAGE FUNCTIONS */ + + /* The first time a page function is called, qpdf will traverse the /Pages tree. Subsequent + * calls to retrieve the number of pages or a specific page run in constant time as they are + * accessing the pages cache. If you manipulate the page tree outside of these functions, you + * should call qpdf_update_all_pages_cache. See comments for getAllPages() and + * updateAllPagesCache() in QPDF.hh. + */ + + /* For each function, the corresponding method in QPDF.hh is referenced. Please see comments in + * QPDF.hh for details. + */ + + /* calls getAllPages(). On error, returns -1 and sets error for qpdf_get_error. */ + QPDF_DLL + int qpdf_get_num_pages(qpdf_data qpdf); + /* returns uninitialized object if out of range */ + QPDF_DLL + qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index); + + /* updateAllPagesCache() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf); + + /* findPage() -- return zero-based index. If page is not found, return -1 and save the error to + * be retrieved with qpdf_get_error. + */ + QPDF_DLL + int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh); + + /* pushInheritedAttributesToPage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf); + + /* Functions that add pages may add pages from other files. If adding a page from the same file, + newpage_qpdf and qpdf are the same. + */ + + /* addPage() */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_add_page(qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first); + /* addPageAt() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_add_page_at( + qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL before, qpdf_oh refpage); + /* removePage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page); + + /* GLOBAL OPTIONS AND SETTINGS */ + + QPDF_DLL + /** + * @brief Retrieves a 32-bit unsigned integer value associated with a global option or limit. + * + * This function allows querying of specific parameters, identified by the qpdf_param_e enum, + * and retrieves their associated unsigned 32-bit integer values. The result will be stored in + * the variable pointed to by `value`. For details about the available parameters and their + * meanings see `qpdf/global.hh`. + * + * @param param[in] The parameter for which the value is being retrieved. This must be a valid + * value from the qpdf_param_e enumeration. + * @param value[out] A pointer to a uint32_t to store the retrieved value. This must be a valid, + * non-null pointer. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_get_uint32(enum qpdf_param_e param, uint32_t* value); + + QPDF_DLL + /** + * @brief Sets a global option or limit for the qpdf library to a specified value. + * + * This function is used to configure global options or limits for the qpdf library based on the + * provided parameter and value. The behavior depends on the specific `param` provided and its + * valid range of values. For details about the available parameters and their meanings see + * `qpdf/global.hh`. + * + * @param param[in] The parameter to be set. Must be one of the values defined in the + * qpdf_param_e enumeration. + * @param value[in] The value to assign to the specified parameter. Interpretation of this value + * depends on the parameter being set. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_set_uint32(enum qpdf_param_e param, uint32_t value); +#ifdef __cplusplus +} + +// These C++ functions make it easier to write C++ code that interoperates with the C API. +// See examples/extend-c-api. + +# include +# include + +# include + +// Retrieve the real QPDF object attached to this qpdf_data. +QPDF_DLL +std::shared_ptr qpdf_c_get_qpdf(qpdf_data qpdf); + +// Wrap a C++ function that may throw an exception to translate the exception for retrieval using +// the normal QPDF C API methods. +QPDF_DLL +QPDF_ERROR_CODE qpdf_c_wrap(qpdf_data qpdf, std::function fn); +#endif + +#endif /* QPDF_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdfjob-c.h b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdfjob-c.h new file mode 100644 index 0000000..a00b923 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdfjob-c.h @@ -0,0 +1,156 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFJOB_C_H +#define QPDFJOB_C_H + +/* + * This file defines a basic "C" API for QPDFJob. See also qpdf-c.h, which defines an API that + * exposes more of the library's API. This API is primarily intended to make it simpler for programs + * in languages other than C++ to incorporate functionality that could be run directly from the + * command-line. + */ + +#include +#include +#include +#include +#ifndef QPDF_NO_WCHAR_T +# include +#endif + +/* + * This file provides a minimal wrapper around QPDFJob. See examples/qpdfjob-c.c for an example of + * its use. + */ + +#ifdef __cplusplus +extern "C" { +#endif + /* SHORT INTERFACE -- These functions are single calls that take care of the whole life cycle of + * QPDFJob. They can be used for one-shot operations where no additional configuration is + * needed. See FULL INTERFACE below. */ + + /* This function does the equivalent of running the qpdf command-line with the given arguments + * and returns the exit code that qpdf would use. argv must be a null-terminated array of + * null-terminated UTF8-encoded strings. If calling this from wmain on Windows, use + * qpdfjob_run_from_wide_argv instead. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_argv(char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_run_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_run_from_wide_argv(wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function runs QPDFJob from a job JSON file. See the "QPDF Job" section of the manual for + * details. The JSON string must be UTF8-encoded. It returns the error code that qpdf would + * return with the equivalent command-line invocation. Exit code values are defined in + * Constants.h in the qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_json(char const* json); + + /* FULL INTERFACE -- new in qpdf11. Similar to the qpdf-c.h API, you must call qpdfjob_init to + * get a qpdfjob_handle and, when done, call qpdfjob_cleanup to free resources. Remaining + * methods take qpdfjob_handle as an argument. This interface requires more calls but also + * offers greater flexibility. + */ + typedef struct _qpdfjob_handle* qpdfjob_handle; + QPDF_DLL + qpdfjob_handle qpdfjob_init(); + + QPDF_DLL + void qpdfjob_cleanup(qpdfjob_handle* j); + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdfjob_set_logger(qpdfjob_handle j, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdfjob_get_logger(qpdfjob_handle j); + + /* This function wraps QPDFJob::initializeFromArgv. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_initialize_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_initialize_from_wide_argv(qpdfjob_handle j, wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function wraps QPDFJob::initializeFromJson. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions using this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json); + + /* This function wraps QPDFJob::run. It returns the error code that qpdf would return with the + * equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run(qpdfjob_handle j); + + /* The following two functions allow a job to be run in two stages - creation of a qpdf_data + * object and writing of the qpdf_data object. This allows the qpdf_data object to be modified + * prior to writing it out. See examples/qpdfjob-remove-annotations for a C++ illustration of + * its use. + * + * This function wraps QPDFJob::createQPDF. It runs the first stage of the job. A nullptr is + * returned if the job did not produce any pdf file to be written. + */ + QPDF_DLL + qpdf_data qpdfjob_create_qpdf(qpdfjob_handle j); + + /* This function wraps QPDFJob::writeQPDF. It returns the error code that qpdf would return with + * the equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. NOTE it is the callers responsibility to clean up the resources + * associated with the qpdf_data object by calling qpdf_cleanup after the call to + * qpdfjob_write_qpdf. + */ + QPDF_DLL + int qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf); + + /* Allow specification of a custom progress reporter. The progress reporter is only used if + * progress is otherwise requested (with the --progress option or "progress": "" in the JSON). + */ + QPDF_DLL + void qpdfjob_register_progress_reporter( + qpdfjob_handle j, void (*report_progress)(int percent, void* data), void* data); + +#ifdef __cplusplus +} +#endif + +#endif /* QPDFJOB_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdflogger-c.h b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdflogger-c.h new file mode 100644 index 0000000..b3d706a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/qpdf/qpdflogger-c.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFLOGGER_H +#define QPDFLOGGER_H + +/* + * This file provides a C API for QPDFLogger. See QPDFLogger.hh for information about the logger and + * examples/qpdfjob-c-save-attachment.c for an example. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /* To operate on a logger, you need a handle to it. call qpdflogger_default_logger to get a + * handle for the default logger. There are functions in qpdf-c.h and qpdfjob-c.h that also take + * or return logger handles. When you're done with the logger handler, call qpdflogger_cleanup. + * This cleans up the handle but leaves the underlying log object intact. (It uses a shared + * pointer and will be cleaned up automatically when it is no longer in use.) That means you can + * create a logger with qpdflogger_create(), pass the logger handle to a function in qpdf-c.h or + * qpdfjob-c.h, and then clean it up, subject to constraints imposed by the other function. + */ + + typedef struct _qpdflogger_handle* qpdflogger_handle; + QPDF_DLL + qpdflogger_handle qpdflogger_default_logger(); + + /* Calling cleanup on the handle returned by qpdflogger_create destroys the handle but not the + * underlying logger. See comments above. + */ + QPDF_DLL + qpdflogger_handle qpdflogger_create(); + + QPDF_DLL + void qpdflogger_cleanup(qpdflogger_handle* l); + + enum qpdf_log_dest_e { + qpdf_log_dest_default = 0, + qpdf_log_dest_stdout = 1, + qpdf_log_dest_stderr = 2, + qpdf_log_dest_discard = 3, + qpdf_log_dest_custom = 4, + }; + + /* Function should return 0 on success. */ + typedef int (*qpdf_log_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + void qpdflogger_set_info( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_warn( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_error( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + + /* A non-zero value for only_if_not_set means that the save pipeline will only be changed if it + * is not already set. + */ + QPDF_DLL + void qpdflogger_set_save( + qpdflogger_handle l, + enum qpdf_log_dest_e dest, + qpdf_log_fn_t fn, + void* udata, + int only_if_not_set); + QPDF_DLL + void qpdflogger_save_to_standard_output(qpdflogger_handle l, int only_if_not_set); + + /* For testing */ + QPDF_DLL + int qpdflogger_equal(qpdflogger_handle l1, qpdflogger_handle l2); + +#ifdef __cplusplus +} +#endif + +#endif // QPDFLOGGER_H diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/turbojpeg.h b/app/src/main/cpp/third_party/pdf-android/x86/include/turbojpeg.h new file mode 100644 index 0000000..9255aee --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/turbojpeg.h @@ -0,0 +1,2923 @@ +/* + * Copyright (C) 2009-2015, 2017, 2020-2026 D. R. Commander + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TURBOJPEG_H__ +#define __TURBOJPEG_H__ + +#include + +#define TURBOJPEG_VERSION_NUMBER 3002000 + +#if defined(_WIN32) && defined(DLLDEFINE) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +#define DLLCALL + + +/** + * @addtogroup TurboJPEG + * TurboJPEG API. This API provides an interface for generating, decoding, and + * transforming planar YUV and JPEG images in memory. + * + * @anchor YUVnotes + * YUV Image Format Notes + * ---------------------- + * Technically, the JPEG format uses the YCbCr colorspace (which is technically + * not a colorspace but a color transform), but per the convention of the + * digital video community, the TurboJPEG API uses "YUV" to refer to an image + * format consisting of Y, Cb, and Cr image planes. + * + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (1 in the case of 4:4:4, grayscale, 4:4:0, or 4:4:1; 2 in + * the case of 4:2:2, 4:2:0, or 2:4; 4 in the case of 4:1:1 or 4:1:0.) + * Similarly, the luminance plane height is the image height padded to the + * nearest multiple of the vertical subsampling factor (1 in the case of 4:4:4, + * 4:2:2, grayscale, or 4:1:1; 2 in the case of 4:2:0, 4:4:0, or 4:1:0; 4 in + * the case of 4:4:1 or 2:4.) This is irrespective of any additional padding + * that may be specified as an argument to the various YUV functions. The + * chrominance plane width is equal to the luminance plane width divided by the + * horizontal subsampling factor, and the chrominance plane height is equal to + * the luminance plane height divided by the vertical subsampling factor. + * + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a row alignment + * of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, + * and each of the chrominance planes would be 20 x 35 bytes. + * + * @{ + */ + + +/** + * The number of initialization options + */ +#define TJ_NUMINIT 3 + +/** + * Initialization options + */ +enum TJINIT { + /** + * Initialize the TurboJPEG instance for compression. + */ + TJINIT_COMPRESS, + /** + * Initialize the TurboJPEG instance for decompression. + */ + TJINIT_DECOMPRESS, + /** + * Initialize the TurboJPEG instance for lossless transformation (both + * compression and decompression.) + */ + TJINIT_TRANSFORM +}; + + +/** + * The number of chrominance subsampling options + */ +#define TJ_NUMSAMP 9 + +/** + * Chrominance subsampling options + * + * When pixels are converted from RGB to YCbCr (see #TJCS_YCbCr) or from CMYK + * to YCCK (see #TJCS_YCCK) as part of the JPEG compression process, some of + * the Cb and Cr (chrominance) components can be discarded or averaged together + * to produce a smaller image with little perceptible loss of image quality. + * (The human eye is more sensitive to small changes in brightness than to + * small changes in color.) This is called "chrominance subsampling". + */ +enum TJSAMP { + /** + * 4:4:4 chrominance subsampling (no chrominance subsampling) + * + * The JPEG or YUV image will contain one chrominance component for every + * pixel in the source image. + */ + TJSAMP_444, + /** + * 4:2:2 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x1 + * block of pixels in the source image. + */ + TJSAMP_422, + /** + * 4:2:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x2 + * block of pixels in the source image. + */ + TJSAMP_420, + /** + * Grayscale + * + * The JPEG or YUV image will contain no chrominance components. + */ + TJSAMP_GRAY, + /** + * 4:4:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x2 + * block of pixels in the source image. + * + * @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_440, + /** + * 4:1:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x1 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:1:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:1:1 is + * better able to reproduce sharp horizontal features. + * + * @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_411, + /** + * 4:4:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x4 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:4:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:4:1 is + * better able to reproduce sharp vertical features. + * + * @note 4:4:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_441, + /** + * 4:1:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x2 + * block of pixels in the source image. 4:1:0 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 4:1:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_410, + /** + * 2:4 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x4 + * block of pixels in the source image. 2:4 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 2:4 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_24, + /** + * Unknown subsampling + * + * The JPEG image uses an unusual type of chrominance subsampling. Such + * images can be decompressed into packed-pixel images, but they cannot be + * - decompressed into planar YUV images, + * - losslessly transformed if #TJXOPT_CROP is specified and #TJXOPT_GRAY is + * not specified, or + * - partially decompressed using a cropping region. + */ + TJSAMP_UNKNOWN = -1 +}; + +/** + * iMCU width (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUWidth[TJ_NUMSAMP] = { 8, 16, 16, 8, 8, 32, 8, 32, 16 }; + +/** + * iMCU height (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUHeight[TJ_NUMSAMP] = { 8, 8, 16, 8, 16, 8, 32, 16, 32 }; + + +/** + * The number of pixel formats + */ +#define TJ_NUMPF 12 + +/** + * Pixel formats + */ +enum TJPF { + /** + * RGB pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. + */ + TJPF_RGB, + /** + * BGR pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. + */ + TJPF_BGR, + /** + * RGBX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_RGBX, + /** + * BGRX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_BGRX, + /** + * XBGR pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XBGR, + /** + * XRGB pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XRGB, + /** + * Grayscale pixel format + * + * Each 1-sample pixel represents a luminance (brightness) level from 0 to + * the maximum sample value (which is, for instance, 255 for 8-bit samples or + * 4095 for 12-bit samples or 65535 for 16-bit samples.) + */ + TJPF_GRAY, + /** + * RGBA pixel format + * + * This is the same as @ref TJPF_RGBX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_RGBA, + /** + * BGRA pixel format + * + * This is the same as @ref TJPF_BGRX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_BGRA, + /** + * ABGR pixel format + * + * This is the same as @ref TJPF_XBGR, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ABGR, + /** + * ARGB pixel format + * + * This is the same as @ref TJPF_XRGB, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ARGB, + /** + * CMYK pixel format + * + * Unlike RGB, which is an additive color model used primarily for display, + * CMYK (Cyan/Magenta/Yellow/Key) is a subtractive color model used primarily + * for printing. In the CMYK color model, the value of each color component + * typically corresponds to an amount of cyan, magenta, yellow, or black ink + * that is applied to a white background. In order to convert between CMYK + * and RGB, it is necessary to use a color management system (CMS.) A CMS + * will attempt to map colors within the printer's gamut to perceptually + * similar colors in the display's gamut and vice versa, but the mapping is + * typically not 1:1 or reversible, nor can it be defined with a simple + * formula. Thus, such a conversion is out of scope for a codec library. + * However, the TurboJPEG API allows for compressing packed-pixel CMYK images + * into YCCK JPEG images (see #TJCS_YCCK) and decompressing YCCK JPEG images + * into packed-pixel CMYK images. + */ + TJPF_CMYK, + /** + * Unknown pixel format + * + * Currently this is only used by #tj3LoadImage8(), #tj3LoadImage12(), and + * #tj3LoadImage16(). + */ + TJPF_UNKNOWN = -1 +}; + +/** + * Red offset (in samples) for a given pixel format + * + * This specifies the number of samples that the red component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the red + * component is `pixel[tjRedOffset[TJPF_BGRX]]`. The offset is -1 if the pixel + * format does not have a red component. + */ +static const int tjRedOffset[TJ_NUMPF] = { + 0, 2, 0, 2, 3, 1, -1, 0, 2, 3, 1, -1 +}; +/** + * Green offset (in samples) for a given pixel format + * + * This specifies the number of samples that the green component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the green + * component is `pixel[tjGreenOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a green component. + */ +static const int tjGreenOffset[TJ_NUMPF] = { + 1, 1, 1, 1, 2, 2, -1, 1, 1, 2, 2, -1 +}; +/** + * Blue offset (in samples) for a given pixel format + * + * This specifies the number of samples that the blue component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the blue + * component is `pixel[tjBlueOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a blue component. + */ +static const int tjBlueOffset[TJ_NUMPF] = { + 2, 0, 2, 0, 1, 3, -1, 2, 0, 1, 3, -1 +}; +/** + * Alpha offset (in samples) for a given pixel format + * + * This specifies the number of samples that the alpha component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRA is stored in `unsigned char pixel[]`, then the alpha + * component is `pixel[tjAlphaOffset[TJPF_BGRA]]`. The offset is -1 if the + * pixel format does not have an alpha component. + */ +static const int tjAlphaOffset[TJ_NUMPF] = { + -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; +/** + * Pixel size (in samples) for a given pixel format + */ +static const int tjPixelSize[TJ_NUMPF] = { + 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4 +}; + + +/** + * The number of JPEG colorspaces + */ +#define TJ_NUMCS 5 + +/** + * JPEG colorspaces + */ +enum TJCS { + /** + * RGB colorspace + * + * When generating the JPEG image, the R, G, and B components in the source + * image are reordered into image planes, but no colorspace conversion or + * subsampling is performed. RGB JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats, but they cannot be generated from or + * decompressed to planar YUV images. + */ + TJCS_RGB, + /** + * YCbCr colorspace + * + * YCbCr is not an absolute colorspace but rather a mathematical + * transformation of RGB designed solely for storage and transmission. YCbCr + * images must be converted to RGB before they can be displayed. In the + * YCbCr colorspace, the Y (luminance) component represents the black & white + * portion of the original image, and the Cb and Cr (chrominance) components + * represent the color portion of the original image. Historically, the + * analog equivalent of this transformation allowed the same signal to be + * displayed to both black & white and color televisions, but JPEG images + * primarily use YCbCr because it optionally allows the color data to be + * subsampled in order to reduce network and disk usage. YCbCr is the most + * common JPEG colorspace, and YCbCr JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats. YCbCr JPEG images can also be generated from + * and decompressed to planar YUV images. + */ + TJCS_YCbCr, + /** + * Grayscale colorspace + * + * The JPEG image retains only the luminance data (Y component), and any + * color data from the source image is discarded. Grayscale JPEG images can + * be generated from and decompressed to packed-pixel images with any of the + * extended RGB or grayscale pixel formats, or they can be generated from + * and decompressed to planar YUV images. + */ + TJCS_GRAY, + /** + * CMYK colorspace + * + * When generating the JPEG image, the C, M, Y, and K components in the + * source image are reordered into image planes, but no colorspace conversion + * or subsampling is performed. CMYK JPEG images can only be generated from + * and decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_CMYK, + /** + * YCCK colorspace + * + * YCCK (AKA "YCbCrK") is not an absolute colorspace but rather a + * mathematical transformation of CMYK designed solely for storage and + * transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + * reversibly transformed into YCCK, and as with YCbCr, the chrominance + * components in the YCCK pixels can be subsampled without incurring major + * perceptual loss. YCCK JPEG images can only be generated from and + * decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_YCCK, + /** + * Default colorspace + * + * Generate a grayscale JPEG image if #TJPARAM_SUBSAMP is set to + * #TJSAMP_GRAY, a YCCK JPEG image if the source image is CMYK, and a YCbCr + * JPEG image otherwise. + */ + TJCS_DEFAULT = -1 +}; + + +/** + * Parameters + */ +enum TJPARAM { + /** + * Error handling behavior + * + * **Value** + * - `0` *[default]* Allow the current compression/decompression/transform + * operation to complete unless a fatal error is encountered. + * - `1` Immediately discontinue the current + * compression/decompression/transform operation if a warning (non-fatal + * error) occurs. + */ + TJPARAM_STOPONWARNING, + /** + * Row order in packed-pixel source/destination images + * + * **Value** + * - `0` *[default]* top-down (X11) order + * - `1` bottom-up (Windows, OpenGL) order + */ + TJPARAM_BOTTOMUP, + /** + * JPEG destination buffer (re)allocation [compression, lossless + * transformation] + * + * **Value** + * - `0` *[default]* Attempt to allocate or reallocate the JPEG destination + * buffer as needed. + * - `1` Generate an error if the JPEG destination buffer is invalid or too + * small. + */ + TJPARAM_NOREALLOC, + /** + * Perceptual quality of lossy JPEG images [compression only] + * + * **Value** + * - `1`-`100` (`1` = worst quality but best compression, `100` = best + * quality but worst compression) *[no default; must be explicitly + * specified]* + */ + TJPARAM_QUALITY, + /** + * Chrominance subsampling level + * + * The JPEG or YUV image uses (decompression, decoding) or will use (lossy + * compression, encoding) the specified level of chrominance subsampling. + * + * **Value** + * - One of the @ref TJSAMP "chrominance subsampling options" *[no default; + * must be explicitly specified for lossy compression, encoding, and + * decoding]* + */ + TJPARAM_SUBSAMP, + /** + * JPEG width (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGWIDTH, + /** + * JPEG height (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGHEIGHT, + /** + * Data precision (bits per sample) + * + * The JPEG image uses (decompression) or will use (lossless compression) the + * specified number of bits per sample. This parameter also specifies the + * target data precision when loading a PNG or PBMPLUS file with + * #tj3LoadImage8(), #tj3LoadImage12(), or #tj3LoadImage16() and the source + * data precision when saving a PNG or PBMPLUS file with #tj3SaveImage8(), + * #tj3SaveImage12(), or #tj3SaveImage16(). + * + * The data precision is the number of bits in the maximum sample value, + * which may not be the same as the width of the data type used to store the + * sample. + * + * **Value** + * - `8` or `12` for lossy JPEG images; `2` to `16` for lossless JPEG, PNG, + * and PBMPLUS images + * + * 12-bit JPEG data precision implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is set. + */ + TJPARAM_PRECISION, + /** + * JPEG colorspace + * + * The JPEG image uses (decompression) or will use (lossy compression) the + * specified colorspace. + * + * **Value** + * - One of the @ref TJCS "JPEG colorspaces" *[default for lossy compression: + * automatically selected based on the subsampling level and pixel format]* + */ + TJPARAM_COLORSPACE, + /** + * Chrominance upsampling algorithm [lossy decompression only] + * + * **Value** + * - `0` *[default]* Use smooth upsampling when decompressing a JPEG image + * that was generated using 4:2:2, 4:2:0, or 4:4:0 chrominance subsampling. + * This creates a smooth transition between neighboring chrominance + * components in order to reduce upsampling artifacts in the decompressed + * image. + * - `1` Use the fastest chrominance upsampling algorithm available, which + * may combine upsampling with color conversion. + */ + TJPARAM_FASTUPSAMPLE, + /** + * DCT/IDCT algorithm [lossy compression and decompression] + * + * **Value** + * - `0` *[default]* Use the most accurate DCT/IDCT algorithm available. + * - `1` Use the fastest DCT/IDCT algorithm available. + * + * This parameter is provided mainly for backward compatibility with libjpeg, + * which historically implemented several different DCT/IDCT algorithms + * because of performance limitations with 1990s CPUs. In the libjpeg-turbo + * implementation of the TurboJPEG API: + * - The "fast" and "accurate" DCT/IDCT algorithms perform similarly on + * modern x86/x86-64 CPUs that support AVX2 instructions. + * - The "fast" algorithm is generally only about 5-15% faster than the + * "accurate" algorithm on other types of CPUs. + * - The difference in accuracy between the "fast" and "accurate" algorithms + * is the most pronounced at JPEG quality levels above 90 and tends to be + * more pronounced with decompression than with compression. + * - For JPEG quality levels above 97, the "fast" algorithm degrades and is + * not fully accelerated, so it is slower than the "accurate" algorithm. + */ + TJPARAM_FASTDCT, + /** + * Huffman table optimization [lossy compression, lossless transformation] + * + * **Value** + * - `0` *[default]* The JPEG image will use the default Huffman tables. + * - `1` Optimal Huffman tables will be computed for the JPEG image. For + * lossless transformation, this can also be specified using + * #TJXOPT_OPTIMIZE. + * + * Huffman table optimization improves compression slightly (generally 5% or + * less), but it reduces compression performance considerably. + */ + TJPARAM_OPTIMIZE, + /** + * Progressive JPEG + * + * In a progressive JPEG image, the DCT coefficients are split across + * multiple "scans" of increasing quality. Thus, a low-quality scan + * containing the lowest-frequency DCT coefficients can be transmitted first + * and refined with subsequent higher-quality scans containing + * higher-frequency DCT coefficients. When using Huffman entropy coding, the + * progressive JPEG format also provides an "end-of-bands (EOB) run" feature + * that allows large groups of zeroes, potentially spanning multiple MCUs, + * to be represented using only a few bytes. + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image is (decompression) or will be (compression, lossless transformation) + * single-scan. + * - `1` The lossy JPEG image is (decompression) or will be (compression, + * lossless transformation) progressive. For lossless transformation, this + * can also be specified using #TJXOPT_PROGRESSIVE. + * + * Progressive JPEG images generally have better compression ratios than + * single-scan JPEG images (much better if the image has large areas of solid + * color), but progressive JPEG compression and decompression is considerably + * slower than single-scan JPEG compression and decompression. Can be + * combined with #TJPARAM_ARITHMETIC. Implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is also set. + */ + TJPARAM_PROGRESSIVE, + /** + * Progressive JPEG scan limit for lossy JPEG images [decompression, lossless + * transformation] + * + * Setting this parameter causes the decompression and transform functions to + * return an error if the number of scans in a progressive JPEG image exceeds + * the specified limit. The primary purpose of this is to allow + * security-critical applications to guard against an exploit of the + * progressive JPEG format described in + * this report. + * + * **Value** + * - maximum number of progressive JPEG scans that the decompression and + * transform functions will process *[default: `0` (no limit)]* + * + * @see #TJPARAM_PROGRESSIVE + */ + TJPARAM_SCANLIMIT, + /** + * Arithmetic entropy coding + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image uses (decompression) or will use (compression, lossless + * transformation) Huffman entropy coding. + * - `1` The lossy JPEG image uses (decompression) or will use (compression, + * lossless transformation) arithmetic entropy coding. For lossless + * transformation, this can also be specified using #TJXOPT_ARITHMETIC. + * + * Arithmetic entropy coding generally improves compression relative to + * Huffman entropy coding, but it reduces compression and decompression + * performance considerably. Can be combined with #TJPARAM_PROGRESSIVE. + */ + TJPARAM_ARITHMETIC, + /** + * Lossless JPEG + * + * **Value** + * - `0` *[default for compression]* The JPEG image is (decompression) or + * will be (compression) lossy/DCT-based. + * - `1` The JPEG image is (decompression) or will be (compression) + * lossless/predictive. + * + * In most cases, lossless JPEG compression and decompression is considerably + * slower than lossy JPEG compression and decompression, and lossless JPEG + * images are much larger than lossy JPEG images. Thus, lossless JPEG images + * are typically used only for applications that require mathematically + * lossless compression. Also note that the following features are not + * available with lossless JPEG images: + * - Colorspace conversion (lossless JPEG images always use #TJCS_RGB, + * #TJCS_GRAY, or #TJCS_CMYK, depending on the pixel format of the source + * image) + * - Chrominance subsampling (lossless JPEG images always use #TJSAMP_444) + * - JPEG quality selection + * - DCT/IDCT algorithm selection + * - Progressive JPEG + * - Arithmetic entropy coding + * - Compression from/decompression to planar YUV images (this parameter is + * ignored by #tj3CompressFromYUV8() and #tj3CompressFromYUVPlanes8()) + * - Decompression scaling + * - Lossless transformation + * + * @see #TJPARAM_LOSSLESSPSV, #TJPARAM_LOSSLESSPT + */ + TJPARAM_LOSSLESS, + /** + * Lossless JPEG predictor selection value (PSV) + * + * **Value** + * - `1`-`7` *[default for compression: `1`]* + * + * Lossless JPEG compression shares no algorithms with lossy JPEG + * compression. Instead, it uses differential pulse-code modulation (DPCM), + * an algorithm whereby each sample is encoded as the difference between the + * sample's value and a "predictor", which is based on the values of + * neighboring samples. If Ra is the sample immediately to the left of the + * current sample, Rb is the sample immediately above the current sample, and + * Rc is the sample diagonally to the left and above the current sample, then + * the relationship between the predictor selection value and the predictor + * is as follows: + * + * PSV | Predictor + * ----|---------- + * 1 | Ra + * 2 | Rb + * 3 | Rc + * 4 | Ra + Rb – Rc + * 5 | Ra + (Rb – Rc) / 2 + * 6 | Rb + (Ra – Rc) / 2 + * 7 | (Ra + Rb) / 2 + * + * Predictors 1-3 are 1-dimensional predictors, whereas Predictors 4-7 are + * 2-dimensional predictors. The best predictor for a particular image + * depends on the image. + * + * @see #TJPARAM_LOSSLESS + */ + TJPARAM_LOSSLESSPSV, + /** + * Lossless JPEG point transform (Pt) + * + * **Value** + * - `0` through ***precision*** *- 1*, where ***precision*** is the JPEG + * data precision in bits *[default for compression: `0`]* + * + * A point transform value of `0` is necessary in order to generate a fully + * lossless JPEG image. (A non-zero point transform value right-shifts the + * input samples by the specified number of bits, which is effectively a form + * of lossy color quantization.) + * + * @see #TJPARAM_LOSSLESS, #TJPARAM_PRECISION + */ + TJPARAM_LOSSLESSPT, + /** + * JPEG restart marker interval in MCUs [lossy compression, + * lossless transformation] + * + * The nature of entropy coding is such that a corrupt JPEG image cannot + * be decompressed beyond the point of corruption unless it contains restart + * markers. A restart marker stops and restarts the entropy coding algorithm + * so that, if a JPEG image is corrupted, decompression can resume at the + * next marker. Thus, adding more restart markers improves the fault + * tolerance of the JPEG image, but adding too many restart markers can + * adversely affect the compression ratio and performance. + * + * In typical JPEG images, an MCU (Minimum Coded Unit) is the minimum set of + * interleaved "data units" (8x8 DCT blocks if the image is lossy or samples + * if the image is lossless) necessary to represent at least one data unit + * per component. (For example, an MCU in an interleaved lossy JPEG image + * that uses 4:2:2 subsampling consists of two luminance blocks followed by + * one block for each chrominance component.) In single-component or + * non-interleaved JPEG images, an MCU is the same as a data unit. + * + * **Value** + * - the number of MCUs between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTROWS to 0. + */ + TJPARAM_RESTARTBLOCKS, + /** + * JPEG restart marker interval in MCU rows [compression, + * lossless transformation] + * + * See #TJPARAM_RESTARTBLOCKS for a description of restart markers and MCUs. + * An MCU row is a row of MCUs spanning the entire width of the image. + * + * **Value** + * - the number of MCU rows between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTBLOCKS to + * 0. + */ + TJPARAM_RESTARTROWS, + /** + * JPEG horizontal pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified horizontal pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_XDENSITY, + /** + * JPEG vertical pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified vertical pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_YDENSITY, + /** + * JPEG pixel density units + * + * **Value** + * - `0` *[default for compression]* The pixel density of the JPEG image is + * expressed (decompression) or will be expressed (compression) in unknown + * units. + * - `1` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/inch. + * - `2` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/cm. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_XDENSITY, TJPARAM_YDENSITY + */ + TJPARAM_DENSITYUNITS, + /** + * Memory limit for intermediate buffers + * + * **Value** + * - the maximum amount of memory (in megabytes) that will be allocated for + * intermediate buffers, which are used with progressive JPEG compression and + * decompression, Huffman table optimization, lossless JPEG compression, and + * lossless transformation *[default: `0` (no limit)]* + */ + TJPARAM_MAXMEMORY, + /** + * Image size limit [decompression, lossless transformation, packed-pixel + * image loading] + * + * Setting this parameter causes the decompression, transform, and image + * loading functions to return an error if the number of pixels in the source + * image exceeds the specified limit. This allows security-critical + * applications to guard against excessive memory consumption. + * + * **Value** + * - maximum number of pixels that the decompression, transform, and image + * loading functions will process *[default: `0` (no limit)]* + */ + TJPARAM_MAXPIXELS, + /** + * Marker copying behavior [decompression, lossless transformation, + * packed-pixel image I/O] + * + * **Value [lossless transformation]** + * - `0` Do not copy any extra markers (including comments, JFIF thumbnails, + * Exif data, and ICC profile data) from the source image to the destination + * image. + * - `1` Do not copy any extra markers, except comment (COM) markers, from + * the source image to the destination image. + * - `2` *[default]* Copy all extra markers from the source image to the + * destination image. + * - `3` Copy all extra markers, except ICC profile data (APP2 markers), from + * the source image to the destination image. + * - `4` Do not copy any extra markers, except ICC profile data (APP2 + * markers), from the source image to the destination image. + * + * #TJXOPT_COPYNONE overrides this parameter for a particular transform. + * This parameter overrides any ICC profile that was previously associated + * with the TurboJPEG instance using #tj3SetICCProfile(), #tj3LoadImage8(), + * #tj3LoadImage12(), or #tj3LoadImage16(). + * + * If this parameter is set to `2` or `4`: + * - When decompressing, #tj3DecompressHeader() extracts the ICC profile from + * a JPEG image. #tj3GetICCProfile() can then be used to retrieve the + * profile. + * - When loading a PNG image using a TurboJPEG compression instance, + * #tj3LoadImage8(), #tj3LoadImage12(), and #tj3LoadImage16() extract the + * ICC profile from the PNG image and associate the profile with the + * TurboJPEG instance. #tj3GetICCProfile() can then be used to retrieve + * the profile. + * - When saving a PNG image using a TurboJPEG decompression instance, + * #tj3SaveImage8(), #tj3SaveImage12(), and #tj3SaveImage16() transfer the + * ICC profile that was previously extracted from a JPEG image to the PNG + * image. + */ + TJPARAM_SAVEMARKERS +}; + + +/** + * The number of error codes + */ +#define TJ_NUMERR 2 + +/** + * Error codes + */ +enum TJERR { + /** + * The error was non-fatal and recoverable, but the destination image may + * still be corrupt. + */ + TJERR_WARNING, + /** + * The error was fatal and non-recoverable. + */ + TJERR_FATAL +}; + + +/** + * The number of transform operations + */ +#define TJ_NUMXOP 8 + +/** + * Transform operations for #tj3Transform() + */ +enum TJXOP { + /** + * Do not transform the position of the image pixels. + */ + TJXOP_NONE, + /** + * Flip (mirror) image horizontally. This transform is imperfect if there + * are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_HFLIP, + /** + * Flip (mirror) image vertically. This transform is imperfect if there are + * any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_VFLIP, + /** + * Transpose image (flip/mirror along upper left to lower right axis.) This + * transform is always perfect. + */ + TJXOP_TRANSPOSE, + /** + * Transverse transpose image (flip/mirror along upper right to lower left + * axis.) This transform is imperfect if there are any partial iMCUs in the + * image (see #TJXOPT_PERFECT.) + */ + TJXOP_TRANSVERSE, + /** + * Rotate image clockwise by 90 degrees. This transform is imperfect if + * there are any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT90, + /** + * Rotate image 180 degrees. This transform is imperfect if there are any + * partial iMCUs in the image (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT180, + /** + * Rotate image counter-clockwise by 90 degrees. This transform is imperfect + * if there are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT270 +}; + + +/** + * This option causes #tj3Transform() to return an error if the transform is + * not perfect. Lossless transforms operate on iMCUs, the size of which + * depends on the level of chrominance subsampling used (see #tjMCUWidth and + * #tjMCUHeight.) If the image's width or height is not evenly divisible by + * the iMCU size, then there will be partial iMCUs on the right and/or bottom + * edges. It is not possible to move these partial iMCUs to the top or left of + * the image, so any transform that would require that is "imperfect." If this + * option is not specified, then any partial iMCUs that cannot be transformed + * will be left in place, which will create odd-looking strips on the right or + * bottom edge of the image. + */ +#define TJXOPT_PERFECT (1 << 0) +/** + * Discard any partial iMCUs that cannot be transformed. + */ +#define TJXOPT_TRIM (1 << 1) +/** + * Enable lossless cropping. See #tj3Transform() for more information. + */ +#define TJXOPT_CROP (1 << 2) +/** + * Discard the color data in the source image, and generate a grayscale + * destination image. + */ +#define TJXOPT_GRAY (1 << 3) +/** + * Do not generate a destination image. (This can be used in conjunction with + * a custom filter to capture the transformed DCT coefficients without + * transcoding them.) + */ +#define TJXOPT_NOOUTPUT (1 << 4) +/** + * Generate a progressive destination image instead of a single-scan + * destination image. Progressive JPEG images generally have better + * compression ratios than single-scan JPEG images (much better if the image + * has large areas of solid color), but progressive JPEG decompression is + * considerably slower than single-scan JPEG decompression. Can be combined + * with #TJXOPT_ARITHMETIC. Implies #TJXOPT_OPTIMIZE unless #TJXOPT_ARITHMETIC + * is also specified. + */ +#define TJXOPT_PROGRESSIVE (1 << 5) +/** + * Do not copy any extra markers (including Exif and ICC profile data) from the + * source image to the destination image. + */ +#define TJXOPT_COPYNONE (1 << 6) +/** + * Enable arithmetic entropy coding in the destination image. Arithmetic + * entropy coding generally improves compression relative to Huffman entropy + * coding (the default), but it reduces decompression performance considerably. + * Can be combined with #TJXOPT_PROGRESSIVE. + */ +#define TJXOPT_ARITHMETIC (1 << 7) +/** + * Enable Huffman table optimization for the destination image. Huffman table + * optimization improves compression slightly (generally 5% or less.) + */ +#define TJXOPT_OPTIMIZE (1 << 8) + + +/** + * Scaling factor + */ +typedef struct { + /** + * Numerator + */ + int num; + /** + * Denominator + */ + int denom; +} tjscalingfactor; + +/** + * Cropping region + */ +typedef struct { + /** + * The left boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU width (see #tjMCUWidth) of the + * destination image. For decompression, this must be evenly divisible by + * the scaled iMCU width of the source image. + */ + int x; + /** + * The upper boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU height (see #tjMCUHeight) of the + * destination image. + */ + int y; + /** + * The width of the cropping region. Setting this to 0 is the equivalent of + * setting it to the width of the source JPEG image - x. + */ + int w; + /** + * The height of the cropping region. Setting this to 0 is the equivalent of + * setting it to the height of the source JPEG image - y. + */ + int h; +} tjregion; + +/** + * A #tjregion structure that specifies no cropping + */ +static const tjregion TJUNCROPPED = { 0, 0, 0, 0 }; + +/** + * Lossless transform + */ +typedef struct tjtransform { + /** + * Cropping region + */ + tjregion r; + /** + * One of the @ref TJXOP "transform operations" + */ + int op; + /** + * The bitwise OR of one of more of the @ref TJXOPT_ARITHMETIC + * "transform options" + */ + int options; + /** + * Arbitrary data that can be accessed within the body of the callback + * function + */ + void *data; + /** + * A callback function that can be used to modify the DCT coefficients after + * they are losslessly transformed but before they are transcoded to a new + * JPEG image. This allows for custom filters or other transformations to be + * applied in the frequency domain. + * + * @param coeffs pointer to an array of transformed DCT coefficients. (NOTE: + * This pointer is not guaranteed to be valid once the callback returns, so + * applications wishing to hand off the DCT coefficients to another function + * or library should make a copy of them within the body of the callback.) + * + * @param arrayRegion #tjregion structure containing the width and height of + * the array pointed to by `coeffs` as well as its offset relative to the + * component plane. TurboJPEG implementations may choose to split each + * component plane into multiple DCT coefficient arrays and call the callback + * function once for each array. + * + * @param planeRegion #tjregion structure containing the width and height of + * the component plane to which `coeffs` belongs + * + * @param componentID ID number of the component plane to which `coeffs` + * belongs. (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in + * typical JPEG images.) + * + * @param transformID ID number of the transformed image to which `coeffs` + * belongs. This is the same as the index of the transform in the + * `transforms` array that was passed to #tj3Transform(). + * + * @param transform a pointer to a #tjtransform structure that specifies the + * parameters and/or cropping region for this transform + * + * @return 0 if the callback was successful, or -1 if an error occurred. + */ + int (*customFilter) (short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentID, int transformID, + struct tjtransform *transform); +} tjtransform; + +/** + * TurboJPEG instance handle + */ +typedef void *tjhandle; + + +/** + * Compute the scaled value of `dimension` using the given scaling factor. + * This macro performs the integer equivalent of `ceil(dimension * + * scalingFactor)`. + */ +#define TJSCALED(dimension, scalingFactor) \ + (((dimension) * scalingFactor.num + scalingFactor.denom - 1) / \ + scalingFactor.denom) + +/** + * A #tjscalingfactor structure that specifies a scaling factor of 1/1 (no + * scaling) + */ +static const tjscalingfactor TJUNSCALED = { 1, 1 }; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Create a new TurboJPEG instance. + * + * @param initType one of the @ref TJINIT "initialization options" + * + * @return a handle to the newly-created instance, or NULL if an error occurred + * (see #tj3GetErrorStr().) + */ +#ifdef __DOXYGEN__ +DLLEXPORT tjhandle tj3Init(int initType); +#else +#define tj3Init(initType) tj3InitVersion(initType, TURBOJPEG_VERSION_NUMBER) +#endif + +DLLEXPORT tjhandle tj3InitVersion(int initType, int apiVersion); + + +/** + * Destroy a TurboJPEG instance. + * + * @param handle handle to a TurboJPEG instance. If the handle is NULL, then + * this function has no effect. + */ +DLLEXPORT void tj3Destroy(tjhandle handle); + + +/** + * Returns a descriptive error message explaining why the last command failed. + * + * @param handle handle to a TurboJPEG instance, or NULL if the error was + * generated by a global function (but note that retrieving the error message + * for a global function is thread-safe only on platforms that support + * thread-local storage.) + * + * @return a descriptive error message explaining why the last command failed. + */ +DLLEXPORT char *tj3GetErrorStr(tjhandle handle); + + +/** + * Returns a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + * + * @param handle handle to a TurboJPEG instance + * + * @return a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + */ +DLLEXPORT int tj3GetErrorCode(tjhandle handle); + + +/** + * Set the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @param value value of the parameter (refer to @ref TJPARAM + * "parameter documentation") + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3Set(tjhandle handle, int param, int value); + + +/** + * Get the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @return the value of the specified parameter, or -1 if the value is unknown. + */ +DLLEXPORT int tj3Get(tjhandle handle, int param); + + +/** + * Allocate a byte buffer for use with TurboJPEG. You should always use this + * function to allocate the JPEG destination buffer(s) for the compression and + * transform functions unless you are disabling automatic buffer (re)allocation + * (by setting #TJPARAM_NOREALLOC.) + * + * @param bytes the number of bytes to allocate + * + * @return a pointer to a newly-allocated buffer with the specified number of + * bytes. + * + * @see tj3Free() + */ +DLLEXPORT void *tj3Alloc(size_t bytes); + + +/** + * Free a byte buffer previously allocated by TurboJPEG. You should always use + * this function to free JPEG destination buffer(s) that were automatically + * (re)allocated by the compression and transform functions or that were + * manually allocated using #tj3Alloc(). + * + * @param buffer address of the buffer to free. If the address is NULL, then + * this function has no effect. + * + * @see tj3Alloc() + */ +DLLEXPORT void tj3Free(void *buffer); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image with + * the given parameters. The number of bytes returned by this function is + * larger than the size of the uncompressed source image. The reason for this + * is that the JPEG format uses 16-bit coefficients, so it is possible for a + * very high-quality source image with very high-frequency content to expand + * rather than compress when converted to the JPEG format. Such images + * represent very rare corner cases, but since there is no way to predict the + * size of a JPEG image prior to compression, the corner cases have to be + * handled. + * + * @param width width (in pixels) of the image + * + * @param height height (in pixels) of the image + * + * @param jpegSubsamp the level of chrominance subsampling to be used when + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) #TJSAMP_UNKNOWN is treated like + * #TJSAMP_444, since a buffer large enough to hold a JPEG image with no + * subsampling should also be large enough to hold a JPEG image with an + * arbitrary level of subsampling. Note that lossless JPEG images always + * use #TJSAMP_444. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * image, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3JPEGBufSize(int width, int height, int jpegSubsamp); + + +/** + * The size of the buffer (in bytes) required to hold a unified planar YUV + * image with the given parameters. + * + * @param width width (in pixels) of the image + * + * @param align row alignment (in bytes) of the image (must be a power of 2.) + * Setting this parameter to n specifies that each row in each plane of the + * image will be padded to the nearest multiple of n bytes (1 = unpadded.) + * + * @param height height (in pixels) of the image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the image, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVBufSize(int width, int align, int height, int subsamp); + + +/** + * The size of the buffer (in bytes) required to hold a YUV image plane with + * the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: This is the width of + * the whole image, not the plane width. + * + * @param stride bytes per row in the image plane. Setting this to 0 is the + * equivalent of setting it to the plane width. + * + * @param height height (in pixels) of the YUV image. NOTE: This is the height + * of the whole image, not the plane height. + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the YUV image + * plane, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVPlaneSize(int componentID, int width, int stride, + int height, int subsamp); + + +/** + * The plane width of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane width of a YUV image plane with the given parameters, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneWidth(int componentID, int width, int subsamp); + + +/** + * The plane height of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane height of a YUV image plane with the given parameters, or + * 0 if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneHeight(int componentID, int height, int subsamp); + + +/** + * Embed an ICC (International Color Consortium) color management profile in + * JPEG images generated by subsequent compression and lossless transformation + * operations. + * + * @note Lossless transformation operations ignore this ICC profile unless + * #TJXOPT_COPYNONE is specified or #TJPARAM_SAVEMARKERS is set to something + * other than `2` or `4`. Otherwise the ICC profile in the source image takes + * precedence, even if the source image has no ICC profile. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param iccBuf pointer to a byte buffer containing an ICC profile. A copy is + * made of the ICC profile, so this buffer can be freed or reused as soon as + * this function returns. Setting this parameter to NULL or setting `iccSize` + * to 0 removes any ICC profile that was previously associated with the + * TurboJPEG instance. + * + * @param iccSize size of the ICC profile (in bytes.) Setting this parameter + * to 0 or setting `iccBuf` to NULL removes any ICC profile that was previously + * associated with the TurboJPEG instance. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetICCProfile(tjhandle handle, unsigned char *iccBuf, + size_t iccSize); + + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 2 to 8 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 9 to 12 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress12(tjhandle handle, const short *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 13 to 16 bits of + * data precision per sample into a lossless JPEG image with the same data + * precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress16(tjhandle handle, const unsigned short *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Compress a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into + * an 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or + * @ref TJCS_GRAY "grayscale" JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if compressing a grayscale image) that contain a YUV + * source image to be compressed. These planes can be contiguous or + * non-contiguous in memory. The size of each plane should match the value + * returned by #tj3YUVPlaneSize() for the given image width, height, strides, + * and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer to + * @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to create a JPEG image from a subregion of a larger + * planar YUV image. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + int width, const int *strides, + int height, unsigned char **jpegBuf, + size_t *jpegSize); + + +/** + * Compress an 8-bit-per-sample unified planar YUV image into an + * 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or @ref TJCS_GRAY "grayscale" + * JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be compressed. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param align row alignment (in bytes) of the source image (must be a power + * of 2.) Setting this parameter to n indicates that each row in each plane of + * the source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUV8(tjhandle handle, + const unsigned char *srcBuf, int width, + int align, int height, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * color conversion and downsampling (which are accelerated in the + * libjpeg-turbo implementation) but does not execute any of the other steps in + * the JPEG compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if generating a grayscale image) that will receive the + * encoded image. These planes can be contiguous or non-contiguous in memory. + * Use #tj3YUVPlaneSize() to determine the appropriate size for each plane + * based on the image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the plane width (see @ref YUVnotes + * "YUV Image Format Notes".) If `strides` is NULL, then the strides for all + * planes will be set to their respective plane widths. You can adjust the + * strides in order to add an arbitrary amount of row padding to each plane or + * to encode an RGB or grayscale image into a subregion of a larger planar YUV + * image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUVPlanes8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into an + * 8-bit-per-sample unified planar YUV image. This function performs color + * conversion and downsampling (which are accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * image. Use #tj3YUVBufSize() to determine the appropriate size for this + * buffer based on the image width, height, row alignment, and level of + * chrominance subsampling (see #TJPARAM_SUBSAMP.) The Y, U (Cb), and V (Cr) + * image planes will be stored sequentially in the buffer. (Refer to + * @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align); + + +/** + * Retrieve information about a JPEG image without decompressing it, or prime + * the decompressor with quantization and Huffman tables. If a JPEG image is + * passed to this function, then the @ref TJPARAM "parameters" that describe + * the JPEG image will be set when the function returns. If a JPEG image is + * passed to this function and #TJPARAM_SAVEMARKERS is set to `2` or `4`, then + * the ICC profile (if any) will be extracted from the JPEG image. + * (#tj3GetICCProfile() can then be used to retrieve the profile.) + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing a JPEG image or an + * "abbreviated table specification" (AKA "tables-only") datastream. Passing a + * tables-only datastream to this function primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. + * + * @param jpegSize size of the JPEG image or tables-only datastream (in bytes) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressHeader(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize); + + +/** + * Retrieve the ICC (International Color Consortium) color management profile + * (if any) that was previously extracted from a JPEG image or associated with + * a TurboJPEG compression instance. + * + * @note To extract the ICC profile from a JPEG image, call + * #tj3DecompressHeader() with #TJPARAM_SAVEMARKERS set to `2` or `4`. + * + * @note To associate an ICC profile with a TurboJPEG compression instance, + * call #tj3SetICCProfile() or use #tj3LoadImage8(), #tj3LoadImage12(), or + * #tj3LoadImage16() to load a PNG image with #TJPARAM_SAVEMARKERS set to `2` + * or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param iccBuf address of a pointer to a byte buffer. Upon return: + * - If `iccBuf` is not NULL and there is an ICC profile to retrieve, then + * `*iccBuf` will point to a byte buffer containing the ICC profile. This + * buffer should be freed using #tj3Free(). + * - If `iccBuf` is not NULL and there is no ICC profile to retrieve, then + * `*iccBuf` will be NULL. + * - If `iccBuf` is NULL, then only the ICC profile size will be retrieved, and + * the ICC profile can be retrieved later. + * + * @param iccSize address of a size_t variable. Upon return, the variable will + * contain the ICC profile size (or 0 if there is no ICC profile to retrieve.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3GetICCProfile(tjhandle handle, unsigned char **iccBuf, + size_t *iccSize); + + +/** + * Returns a list of fractional scaling factors that the JPEG decompressor + * supports. + * + * @param numScalingFactors pointer to an integer variable that will receive + * the number of elements in the list + * + * @return a pointer to a list of fractional scaling factors, or NULL if an + * error is encountered (see #tj3GetErrorStr().) + */ +DLLEXPORT tjscalingfactor *tj3GetScalingFactors(int *numScalingFactors); + + +/** + * Set the scaling factor for subsequent lossy decompression operations. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param scalingFactor #tjscalingfactor structure that specifies a fractional + * scaling factor that the decompressor supports (see #tj3GetScalingFactors()), + * or #TJUNSCALED for no scaling. Decompression scaling is a function + * of the IDCT algorithm, so scaling factors are generally limited to multiples + * of 1/8. If the entire JPEG image will be decompressed, then the width and + * height of the scaled destination image can be determined by calling + * #TJSCALED() with the JPEG width and height (see #TJPARAM_JPEGWIDTH and + * #TJPARAM_JPEGHEIGHT) and the specified scaling factor. When decompressing + * into a planar YUV image, an intermediate buffer copy will be performed if + * the width or height of the scaled destination image is not an even multiple + * of the iMCU size (see #tjMCUWidth and #tjMCUHeight.) Note that + * decompression scaling is not available (and the specified scaling factor is + * ignored) when decompressing lossless JPEG images (see #TJPARAM_LOSSLESS), + * since the IDCT algorithm is not used with those images. Note also that + * #TJPARAM_FASTDCT is ignored when decompression scaling is enabled. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetScalingFactor(tjhandle handle, + tjscalingfactor scalingFactor); + + +/** + * Set the cropping region for partially decompressing a lossy JPEG image into + * a packed-pixel image + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param croppingRegion #tjregion structure that specifies a subregion of the + * JPEG image to decompress, or #TJUNCROPPED for no cropping. The + * left boundary of the cropping region must be evenly divisible by the scaled + * iMCU width-- #TJSCALED(#tjMCUWidth[subsamp], scalingFactor), where + * `subsamp` is the level of chrominance subsampling in the JPEG image (see + * #TJPARAM_SUBSAMP) and `scalingFactor` is the decompression scaling factor + * (see #tj3SetScalingFactor().) The cropping region should be specified + * relative to the scaled image dimensions. Unless `croppingRegion` is + * #TJUNCROPPED, the JPEG header must be read (see + * #tj3DecompressHeader()) prior to calling this function. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetCroppingRegion(tjhandle handle, tjregion croppingRegion); + + +/** + * Decompress a JPEG image with 2 to 8 bits of data precision per sample into a + * packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * The @ref TJPARAM "parameters" that describe the JPEG image will be set when + * this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel + * decompressed image. This buffer should normally be + * `pitch * destinationHeight` samples in size. However, you can also use this + * parameter to decompress into a specific region of a larger buffer. NOTE: + * If the JPEG image is lossy, then `destinationHeight` is either the scaled + * JPEG height (see #TJSCALED(), #TJPARAM_JPEGHEIGHT, and + * #tj3SetScalingFactor()) or the height of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationHeight` is the JPEG height. + * + * @param pitch samples per row in the destination image. Normally this should + * be set to destinationWidth * #tjPixelSize[pixelFormat], if the + * destination image should be unpadded. (Setting this parameter to 0 is the + * equivalent of setting it to + * destinationWidth * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decompress into a specific region of + * a larger buffer. NOTE: If the JPEG image is lossy, then `destinationWidth` + * is either the scaled JPEG width (see #TJSCALED(), #TJPARAM_JPEGWIDTH, and + * #tj3SetScalingFactor()) or the width of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationWidth` is the JPEG width. + * + * @param pixelFormat pixel format of the destination image (see @ref + * TJPF "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Decompress8(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned char *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a JPEG image with 9 to 12 bits of data precision per sample into + * a packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * + * @note This function can also be used to decompress an 8-bit-per-sample lossy + * JPEG image into a 12-bit-per-sample packed-pixel image. + * + * @note The JPEG format uses 16-bit DCT coefficients and computes those + * coefficients relative to an 8x8 DCT block. Thus, an 8-bit-per-sample JPEG + * image can preserve most of the signal from an underexposed + * higher-data-precision source image, provided that the data precision of the + * source image is retained in the compressor until the forward DCT stage. + * (Modern digital cameras typically do that, but note that libjpeg-turbo does + * not. Our solution for retaining higher data precision in the compressor is + * simply to generate a 12-bit-per-sample JPEG image.) + * + * @note It may be desirable to preserve as much of that signal as possible in + * the decompressor, to facilitate shadow recovery in the decompressed image. + * Thus, calling this function forces the decompressor to use the + * 12-bit-per-sample decompression pipeline even if the JPEG image has 8 bits + * of data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress12(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, short *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a lossless JPEG image with 13 to 16 bits of data precision per + * sample into a packed-pixel RGB, grayscale, or CMYK image with the same + * data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress16(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned short *dstBuf, + int pitch, int pixelFormat); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * JPEG decompression but leaves out the color conversion step, so a planar YUV + * image is generated instead of a packed-pixel image. The + * @ref TJPARAM "parameters" that describe the JPEG image will be set when this + * function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decompressing a grayscale image) that will receive + * the decompressed image. These planes can be contiguous or non-contiguous in + * memory. Use #tj3YUVPlaneSize() to determine the appropriate size for each + * plane based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), + * strides, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer + * to @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the scaled plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective scaled plane widths. + * You can adjust the strides in order to add an arbitrary amount of row + * padding to each plane or to decompress the JPEG image into a subregion of a + * larger planar YUV image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char **dstPlanes, + int *strides); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into an 8-bit-per-sample + * unified planar YUV image. This function performs JPEG decompression but + * leaves out the color conversion step, so a planar YUV image is generated + * instead of a packed-pixel image. The @ref TJPARAM "parameters" that + * describe the JPEG image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * decompressed image. Use #tj3YUVBufSize() to determine the appropriate size + * for this buffer based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes will be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUV8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char *dstBuf, int align); + + +/** + * Decode a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into an + * 8-bit-per-sample packed-pixel RGB or grayscale image. This function + * performs color conversion (which is accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decoding a grayscale image) that contain a YUV image + * to be decoded. These planes can be contiguous or non-contiguous in memory. + * The size of each plane should match the value returned by #tj3YUVPlaneSize() + * for the given image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to decode a subregion of a larger planar YUV image. + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + const int *strides, unsigned char *dstBuf, + int width, int pitch, int height, + int pixelFormat); + + +/** + * Decode an 8-bit-per-sample unified planar YUV image into an 8-bit-per-sample + * packed-pixel RGB or grayscale image. This function performs color + * conversion (which is accelerated in the libjpeg-turbo implementation) but + * does not execute any of the other steps in the JPEG decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be decoded. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * source buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV source image (must be a + * power of 2.) Setting this parameter to n indicates that each row in each + * plane of the YUV source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int align, unsigned char *dstBuf, int width, + int pitch, int height, int pixelFormat); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image + * transformed with the given transform parameters and/or cropping region. + * This function is a wrapper for #tj3JPEGBufSize() that takes into account + * cropping, transposition of the width and height (which affects the + * destination image dimensions and level of chrominance subsampling), + * grayscale conversion, and the ICC profile (if any) that was previously + * associated with the TurboJPEG instance or extracted from the source image + * (see #tj3SetICCProfile(), #tj3GetICCProfile(), and #TJPARAM_SAVEMARKERS.) + * The JPEG header must be read (see #tj3DecompressHeader()) prior to calling + * this function. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param transform pointer to a #tjtransform structure that specifies the + * transform parameters and/or cropping region for the JPEG image. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * transformed image, or 0 if an error occurred (see #tj3GetErrorStr() and + * #tj3GetErrorCode().) + */ +DLLEXPORT size_t tj3TransformBufSize(tjhandle handle, + const tjtransform *transform); + + +/** + * Losslessly transform a JPEG image into another JPEG image. Lossless + * transforms work by moving the raw DCT coefficients from one JPEG image + * structure to another without altering the values of the coefficients. While + * this is typically faster than decompressing the image, transforming it, and + * re-compressing it, lossless transforms are not free. Each lossless + * transform requires reading and performing entropy decoding on all of the + * coefficients in the source image, regardless of the size of the destination + * image. Thus, this function provides a means of generating multiple + * transformed images from the same source or applying multiple transformations + * simultaneously, in order to eliminate the need to read the source + * coefficients multiple times. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param jpegBuf pointer to a byte buffer containing the JPEG source image to + * transform + * + * @param jpegSize size of the JPEG source image (in bytes) + * + * @param n the number of transformed JPEG images to generate + * + * @param dstBufs pointer to an array of n byte buffers. `dstBufs[i]` will + * receive a JPEG image that has been transformed using the parameters in + * `transforms[i]`. TurboJPEG has the ability to reallocate the JPEG + * destination buffer to accommodate the size of the transformed JPEG image. + * Thus, you can choose to: + * -# pre-allocate the JPEG destination buffer with an arbitrary size using + * #tj3Alloc() and let TurboJPEG grow the buffer as needed, + * -# set `dstBufs[i]` to NULL to tell TurboJPEG to allocate the buffer for + * you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3TransformBufSize(). Under normal circumstances, this should ensure that + * the buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC + * guarantees that it won't be. However, if the source image has a large + * amount of embedded Exif data, then the transformed JPEG image may be larger + * than the worst-case size. #TJPARAM_NOREALLOC cannot be used in that case + * unless the embedded data is discarded using #TJXOPT_COPYNONE or + * #TJPARAM_SAVEMARKERS.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `dstBufs[i]` + * upon return from this function, as it may have changed. + * + * @param dstSizes pointer to an array of n size_t variables that will receive + * the actual sizes (in bytes) of each transformed JPEG image. If `dstBufs[i]` + * points to a pre-allocated buffer, then `dstSizes[i]` should be set to the + * size of the buffer. Otherwise, `dstSizes[i]` is ignored. Upon return, + * `dstSizes[i]` will contain the size of the transformed JPEG image (in + * bytes.) + * + * @param transforms pointer to an array of n #tjtransform structures, each of + * which specifies the transform parameters and/or cropping region for the + * corresponding transformed JPEG image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Transform(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, int n, unsigned char **dstBufs, + size_t *dstSizes, const tjtransform *transforms); + + +/** + * Load a packed-pixel image with 2 to 8 bits of data precision per sample from + * disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG, + * PBMPLUS (PPM/PGM), or Windows BMP format. Windows BMP files require + * 8-bit-per-sample data precision. When loading a PNG or PBMPLUS file, the + * target data precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. If the data precision of the PNG or PBMPLUS file does not match + * the target data precision, then upconverting or downconverting will be + * performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function varies depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files and 8-bit-per-pixel BMP files with a + * grayscale colormap can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned char *tj3LoadImage8(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 9 to 12 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 9 to 12 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 12 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT short *tj3LoadImage12(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 13 to 16 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 13 to 16 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 16 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned short *tj3LoadImage16(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + + +/** + * Save a packed-pixel image with 2 to 8 bits of data precision per sample from + * memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image. The + * image will be stored in PNG, PBMPLUS (PPM/PGM), or Windows BMP format, + * depending on the file extension. Windows BMP files require 8-bit-per-sample + * data precision. When saving a PNG or PBMPLUS file, the source data + * precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in grayscale PNG, PGM, or 8-bit-per-pixel (indexed + * color) BMP format. Otherwise, the image will be stored in truecolor PNG, + * PPM, or 24-bit-per-pixel BMP format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage8(tjhandle handle, const char *filename, + const unsigned char *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 9 to 12 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage12(tjhandle handle, const char *filename, + const short *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 13 to 16 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage16(tjhandle handle, const char *filename, + const unsigned short *buffer, int width, + int pitch, int height, int pixelFormat); + + +/* Backward compatibility functions and macros (nothing to see here) */ + +/* TurboJPEG 1.0+ */ + +#define NUMSUBOPT TJ_NUMSAMP +#define TJ_444 TJSAMP_444 +#define TJ_422 TJSAMP_422 +#define TJ_420 TJSAMP_420 +#define TJ_411 TJSAMP_420 +#define TJ_GRAYSCALE TJSAMP_GRAY + +#define TJ_BGR 1 +#define TJ_BOTTOMUP TJFLAG_BOTTOMUP +#define TJ_FORCEMMX TJFLAG_FORCEMMX +#define TJ_FORCESSE TJFLAG_FORCESSE +#define TJ_FORCESSE2 TJFLAG_FORCESSE2 +#define TJ_ALPHAFIRST 64 +#define TJ_FORCESSE3 TJFLAG_FORCESSE3 +#define TJ_FASTUPSAMPLE TJFLAG_FASTUPSAMPLE + +#define TJPAD(width) (((width) + 3) & (~3)) + +DLLEXPORT unsigned long TJBUFSIZE(int width, int height); + +DLLEXPORT int tjCompress(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, unsigned long *compressedSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelSize, + int flags); + +DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height); + +DLLEXPORT int tjDestroy(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr(void); + +DLLEXPORT tjhandle tjInitCompress(void); + +DLLEXPORT tjhandle tjInitDecompress(void); + +/* TurboJPEG 1.1+ */ + +#define TJ_YUV 512 + +DLLEXPORT unsigned long TJBUFSIZEYUV(int width, int height, int jpegSubsamp); + +DLLEXPORT int tjDecompressHeader2(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp); + +DLLEXPORT int tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int flags); + +DLLEXPORT int tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, int subsamp, int flags); + +/* TurboJPEG 1.2+ */ + +#define TJFLAG_BOTTOMUP 2 +#define TJFLAG_FORCEMMX 8 +#define TJFLAG_FORCESSE 16 +#define TJFLAG_FORCESSE2 32 +#define TJFLAG_FORCESSE3 128 +#define TJFLAG_FASTUPSAMPLE 256 +#define TJFLAG_NOREALLOC 1024 + +DLLEXPORT unsigned char *tjAlloc(int bytes); + +DLLEXPORT unsigned long tjBufSize(int width, int height, int jpegSubsamp); + +DLLEXPORT unsigned long tjBufSizeYUV(int width, int height, int subsamp); + +DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int subsamp, int flags); + +DLLEXPORT void tjFree(unsigned char *buffer); + +DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors); + +DLLEXPORT tjhandle tjInitTransform(void); + +DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, int n, + unsigned char **dstBufs, unsigned long *dstSizes, + tjtransform *transforms, int flags); + +/* TurboJPEG 1.2.1+ */ + +#define TJFLAG_FASTDCT 2048 +#define TJFLAG_ACCURATEDCT 4096 + +/* TurboJPEG 1.4+ */ + +DLLEXPORT unsigned long tjBufSizeYUV2(int width, int align, int height, + int subsamp); + +DLLEXPORT int tjCompressFromYUV(tjhandle handle, const unsigned char *srcBuf, + int width, int align, int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + int width, const int *strides, + int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, + int align, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjDecodeYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + const int *strides, int subsamp, + unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags); + +DLLEXPORT int tjDecompressHeader3(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp, + int *jpegColorspace); + +DLLEXPORT int tjDecompressToYUV2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int align, int height, int flags); + +DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, + unsigned char **dstPlanes, int width, + int *strides, int height, int flags); + +DLLEXPORT int tjEncodeYUV3(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align, int subsamp, + int flags); + +DLLEXPORT int tjEncodeYUVPlanes(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags); + +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); + +DLLEXPORT unsigned long tjPlaneSizeYUV(int componentID, int width, int stride, + int height, int subsamp); + +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp); + +/* TurboJPEG 2.0+ */ + +#define TJFLAG_STOPONWARNING 8192 +#define TJFLAG_PROGRESSIVE 16384 + +DLLEXPORT int tjGetErrorCode(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr2(tjhandle handle); + +DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, + int align, int *height, int *pixelFormat, + int flags); + +DLLEXPORT int tjSaveImage(const char *filename, unsigned char *buffer, + int width, int pitch, int height, int pixelFormat, + int flags); + +/* TurboJPEG 2.1+ */ + +#define TJFLAG_LIMITSCANS 32768 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/zconf.h b/app/src/main/cpp/third_party/pdf-android/x86/include/zconf.h new file mode 100644 index 0000000..1ff5e8c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/zconf.h @@ -0,0 +1,555 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* #undef Z_PREFIX */ +#define HAVE_STDARG_H 1 +#define HAVE_UNISTD_H 1 + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compress_z z_compress_z +# define compress2_z z_compress2_z +# define compressBound z_compressBound +# define compressBound_z z_compressBound_z +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateBound_z z_deflateBound_z +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflateUsed z_deflateUsed +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define inflate_fixed z_inflate_fixed +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# define uncompress_z z_uncompress_z +# define uncompress2_z z_uncompress2_z +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#ifndef z_const +# ifdef ZLIB_CONST +# define z_const const +# else +# define z_const +# endif +#endif + +#ifdef Z_SOLO +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if HAVE_UNISTD_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if HAVE_STDARG_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# if defined(__WATCOMC__) || defined(__GO32__) || \ + (defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#elif defined(__MINGW32__) +# define z_off64_t long long +#elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +#elif defined(__GO32__) +# define z_off64_t offset_t +#else +# define z_off64_t z_off_t +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/zlib.h b/app/src/main/cpp/third_party/pdf-android/x86/include/zlib.h new file mode 100644 index 0000000..a57d336 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/zlib.h @@ -0,0 +1,2057 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.3.2, February 17th, 2026 + + Copyright (C) 1995-2026 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 at https://datatracker.ietf.org/doc/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#ifdef ZLIB_BUILD +# include +#else +# include "zconf.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.3.2" +#define ZLIB_VERNUM 0x1320 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 2 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion(void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the input taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_RLE to limit match distances to one (run-length + encoding), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string + matching). Filtered data consists mostly of small values with a somewhat + random distribution, as produced by the PNG filters. In this case, the + compression algorithm is tuned to compress them better. The effect of + Z_FILTERED is to force more Huffman coding and less string matching than the + default; it is intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. + Z_RLE is almost as fast as Z_HUFFMAN_ONLY, but should give better + compression for PNG image data than Huffman only. The degree of string + matching from most to none is: Z_DEFAULT_STRATEGY, Z_FILTERED, Z_RLE, then + Z_HUFFMAN_ONLY. The strategy parameter affects the compression ratio but + never the correctness of the compressed output, even if it is not set + optimally for the given data. Z_FIXED uses the default string matching, but + prevents the use of dynamic Huffman codes, allowing for a simpler decoder + for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); +ZEXTERN z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. + + delfateBound_z() is the same, but takes and returns a size_t length. Note + that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. If an int is 16 bits and memLevel is 9, then + it is possible for the number of pending bytes to not fit in an unsigned. In + that case Z_BUF_ERROR is returned and *pending is set to the maximum value + of an unsigned. + */ + +ZEXTERN int ZEXPORT deflateUsed(z_streamp strm, + int *bits); +/* + deflateUsed() returns in *bits the most recent number of deflate bits used + in the last byte when flushing to a byte boundary. The result is in 1..8, or + 0 if there has not yet been a flush. This helps determine the location of + the last bit of a deflate stream. + + deflateUsed returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); +/* + This function inserts bits in the inflate input stream. The intent is to + use inflatePrime() to start inflating at a bit position in the middle of a + byte. The provided bits will be used before any bytes are used from + next_in. This function should be used with raw inflate, before the first + inflate() call, after inflateInit2() or inflateReset(). It can also be used + after an inflate() return indicates the end of a deflate block or header + when using Z_BLOCK. bits must be less than or equal to 16, and that many of + the least significant bits of value will be inserted in the input. The + other bits in value can be non-zero, and will be ignored. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent, or if bits is out of range. If inflate was + in the middle of processing a header, trailer, or stored block lengths, then + it is possible for there to be only eight bits available in the bit buffer. + In that case, bits > 8 is considered out of range. However, when used as + outlined above, there will always be 16 bits available in the buffer for + insertion. As noted in its documentation above, inflate records the number + of bits in the bit buffer on return in data_type. 32 minus that is the + number of bits available for insertion. inflatePrime does not update + data_type with the new number of bits in buffer. +*/ + +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) The extra, name, and comment pointers + much each be either Z_NULL or point to space to store that information from + the header. If extra is not Z_NULL, then extra_max contains the maximum + number of bytes that can be written to extra. Once done is true, extra_len + contains the actual extra field length, and extra contains the extra field, + or that field truncated if extra_max is less than extra_len. If name is not + Z_NULL, then up to name_max characters, including the terminating zero, are + written there. If comment is not Z_NULL, then up to comm_max characters, + including the terminating zero, are written there. The application can tell + that the name or comment did not fit in the provided space by the absence of + a terminating zero. If any of extra, name, or comment are not present in + the header, then that field's pointer is set to Z_NULL. This allows the use + of deflateSetHeader() with the returned structure to duplicate the header. + Note that if those fields initially pointed to allocated memory, then the + application will need to save them elsewhere so that they can be eventually + freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); + +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (all zeros is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() is not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + 27: 0 = gzprintf() present, 1 = not -- 1 means gzprintf() returns an error + + Remainder: + 28-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. The _z versions of the functions use the size_t + type for lengths. Note that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT compress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); +ZEXTERN int ZEXPORT compress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen, + int level); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); +ZEXTERN z_size_t ZEXPORT compressBound_z(z_size_t sourceLen); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT uncompress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. On entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) On exit, *destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); +ZEXTERN int ZEXPORT uncompress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. 'T' cannot be + used to force transparent reading. Transparent reading is automatically + performed if there is no gzip header at the start. Transparent reading can + be disabled with the 'G' option, which will instead return an error if there + is no gzip header. 'N' will open the file in non-blocking mode. + + 'a' can be used instead of 'w' to request that the gzip stream that will + be written be appended to the file. '+' will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + 'x' when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of 'e' when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. Note that if 'N' is in mode for non-blocking, the + open() itself can fail in order to not block. In that case gzopen() will + return NULL and errno will be EAGAIN or ENONBLOCK. The call to gzopen() can + then be re-tried. If the application would like to block on opening the + file, then it can use open() without O_NONBLOCK, and then gzdopen() with the + resulting file descriptor and 'N' in the mode, which will set it to non- + blocking. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. An + 'e' in mode will set fd's flag to close the file on an execve() call. An 'N' + in mode will set fd's non-blocking flag. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzread() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. If some data was read before an error, then that data is + returned until exhausted, after which the next call will signal the error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as that of fread() implementations in common libraries. This + could result in data loss if used with size != 1 when reading a concurrently + written file or a non-blocking file. In that case, use size == 1 or gzread() + instead. +*/ + +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written, or 0 in case of error or + if len is 0. If the write destination is non-blocking, then gzwrite() may + return a number of bytes written that is not 0 and less than len. + + If len does not fit in an int, then 0 is returned and nothing is written. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. + + If writing a concurrently read file or a non-blocking file with size != 1, + a partial item could be written, with no way of knowing how much of it was + not written, resulting in data loss. In that case, use size == 1 or + gzwrite() instead. +*/ + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); +#else +ZEXTERN int ZEXPORTVA gzprintf(); +#endif +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. + + In that last case, there may also be a buffer overflow with unpredictable + consequences, which is possible only if zlib was compiled with the insecure + functions sprintf() or vsprintf(), because the secure snprintf() and + vsnprintf() functions were not available. That would only be the case for + a non-ANSI C compiler. zlib may have been built without gzprintf() because + secure functions were not available and having gzprintf() be insecure was + not an option, in which case, gzprintf() returns Z_STREAM_ERROR. All of + these possibilities can be determined using zlibCompileFlags(). + + If a Z_BUF_ERROR is returned, then nothing was written due to a stall on + the non-blocking write destination. +*/ + +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. + The number of characters written may be less than the length of the string + if the write destination is non-blocking. + + If the length of the string does not fit in an int, then -1 is returned + and nothing is written. +*/ + +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If some data was read before an error, + then that data is returned until exhausted, after which the next call will + return NULL to signal the error. + + gzgets can be used on a file being concurrently written, and on a non- + blocking device, both as for gzread(). However lines may be broken in the + middle, leaving it up to the application to reassemble them as needed. +*/ + +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc(gzFile file); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 in + case of end of file or error. If some data was read before an error, then + that data is returned until exhausted, after which the next call will return + -1 to signal the error. + + This is implemented as a macro for speed. As such, it does not do all of + the checking the other functions do. I.e. it does not check to see if file + is NULL, nor whether the structure file points to has been clobbered or not. + + gzgetc can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzgetc() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. +*/ + +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). + + gzungetc(-1, file) will force any pending seek to execute. Then gztell() + will report the position, even if the requested seek reached end of file. + This can be used to determine the number of uncompressed bytes in a gzip + file without having to read it into a buffer. +*/ + +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. For reading or writing, any actual seeking is deferred + until the next read or write operation, or close operation when writing. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind(gzFile file); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof(gzFile file); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect(gzFile file); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). If the input is being written concurrently or the device is non- + blocking, then gzdirect() may give a different answer once four bytes of + input have been accumulated, which is what is needed to confirm or deny a + gzip header. Before this, gzdirect() will return true (1). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose(gzFile file); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); +/* + Return the error message for the last error which occurred on file. + If errnum is not NULL, *errnum is set to zlib error number. If an error + occurred in the file system and not in the compression library, *errnum is + set to Z_ERRNO and the application may consult errno to get the exact error + code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr(gzFile file); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); +/* + Same as adler32(), but with a size_t length. Note that a long is 32 bits + on Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); +/* + Same as crc32(), but with a size_t length. Note that a long is 32 bits on + Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. len2 must be non-negative, otherwise zero is returned. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). len2 must be non-negative, otherwise zero is returned. +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/include/zopfli.h b/app/src/main/cpp/third_party/pdf-android/x86/include/zopfli.h new file mode 100644 index 0000000..c079662 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86/include/zopfli.h @@ -0,0 +1,94 @@ +/* +Copyright 2011 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: lode.vandevenne@gmail.com (Lode Vandevenne) +Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala) +*/ + +#ifndef ZOPFLI_ZOPFLI_H_ +#define ZOPFLI_ZOPFLI_H_ + +#include +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Options used throughout the program. +*/ +typedef struct ZopfliOptions { + /* Whether to print output */ + int verbose; + + /* Whether to print more detailed output */ + int verbose_more; + + /* + Maximum amount of times to rerun forward and backward pass to optimize LZ77 + compression cost. Good values: 10, 15 for small files, 5 for files over + several MB in size or it will be too slow. + */ + int numiterations; + + /* + If true, splits the data in multiple deflate blocks with optimal choice + for the block boundaries. Block splitting gives better compression. Default: + true (1). + */ + int blocksplitting; + + /* + No longer used, left for compatibility. + */ + int blocksplittinglast; + + /* + Maximum amount of blocks to split into (0 for unlimited, but this can give + extreme results that hurt compression on some files). Default value: 15. + */ + int blocksplittingmax; +} ZopfliOptions; + +/* Initializes options with default values. */ +void ZopfliInitOptions(ZopfliOptions* options); + +/* Output format */ +typedef enum { + ZOPFLI_FORMAT_GZIP, + ZOPFLI_FORMAT_ZLIB, + ZOPFLI_FORMAT_DEFLATE +} ZopfliFormat; + +/* +Compresses according to the given output format and appends the result to the +output. + +options: global program options +output_type: the output format to use +out: pointer to the dynamic output array to which the result is appended. Must + be freed after use +outsize: pointer to the dynamic output array size +*/ +void ZopfliCompress(const ZopfliOptions* options, ZopfliFormat output_type, + const unsigned char* in, size_t insize, + unsigned char** out, size_t* outsize); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ZOPFLI_ZOPFLI_H_ */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/lib/libjpeg.a b/app/src/main/cpp/third_party/pdf-android/x86/lib/libjpeg.a new file mode 100644 index 0000000..21ca65b Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86/lib/libjpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/lib/libqpdf.a b/app/src/main/cpp/third_party/pdf-android/x86/lib/libqpdf.a new file mode 100644 index 0000000..0416b10 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86/lib/libqpdf.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/lib/libturbojpeg.a b/app/src/main/cpp/third_party/pdf-android/x86/lib/libturbojpeg.a new file mode 100644 index 0000000..97c030b Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86/lib/libturbojpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/lib/libz.a b/app/src/main/cpp/third_party/pdf-android/x86/lib/libz.a new file mode 100644 index 0000000..04921f1 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86/lib/libz.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/lib/libz.so b/app/src/main/cpp/third_party/pdf-android/x86/lib/libz.so new file mode 100644 index 0000000..f406b92 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86/lib/libz.so differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86/lib/libzopfli.a b/app/src/main/cpp/third_party/pdf-android/x86/lib/libzopfli.a new file mode 100644 index 0000000..6cf37fb Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86/lib/libzopfli.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/jconfig.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jconfig.h new file mode 100644 index 0000000..17f95c8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jconfig.h @@ -0,0 +1,60 @@ +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ +#define JPEG_LIB_VERSION 80 + +/* libjpeg-turbo version */ +#define LIBJPEG_TURBO_VERSION 3.1.90 + +/* libjpeg-turbo version in integer form */ +#define LIBJPEG_TURBO_VERSION_NUMBER 3001090 + +/* Support arithmetic encoding when using 8-bit samples */ +#define C_ARITH_CODING_SUPPORTED 1 + +/* Support arithmetic decoding when using 8-bit samples */ +#define D_ARITH_CODING_SUPPORTED 1 + +/* Support in-memory source/destination managers */ +#define MEM_SRCDST_SUPPORTED 1 + +/* Use accelerated SIMD routines when using 8-bit samples */ +/* #undef WITH_SIMD */ + +/* This version of libjpeg-turbo supports run-time selection of data precision, + * so BITS_IN_JSAMPLE is no longer used to specify the data precision at build + * time. However, some downstream software expects the macro to be defined. + * Since 12-bit data precision is an opt-in feature that requires explicitly + * calling 12-bit-specific libjpeg API functions and using 12-bit-specific data + * types, the unmodified portion of the libjpeg API still behaves as if it were + * built for 8-bit precision, and JSAMPLE is still literally an 8-bit data + * type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here. + */ +#ifndef BITS_IN_JSAMPLE +#define BITS_IN_JSAMPLE 8 +#endif + +#ifdef _WIN32 + +#undef RIGHT_SHIFT_IS_UNSIGNED + +/* Define "boolean" as unsigned char, not int, per Windows custom */ +#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ + +/* Define "INT32" as int, not long, per Windows custom */ +#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */ +typedef short INT16; +typedef signed int INT32; +#endif +#define XMD_H /* prevent jmorecfg.h from redefining it */ + +#else + +/* Define if your (broken) compiler shifts signed values as if they were + unsigned. */ +/* #undef RIGHT_SHIFT_IS_UNSIGNED */ + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/jerror.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jerror.h new file mode 100644 index 0000000..892edc3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jerror.h @@ -0,0 +1,336 @@ +/* + * jerror.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2014, 2017, 2021-2023, 2026, D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code, string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code, string) code, + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented") +#endif +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#endif +JMESSAGE(JERR_BAD_DCT_COEF, + "DCT coefficient (lossy) or spatial difference (lossless) out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive/lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Requested features are incompatible") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Memory limit exceeded") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#if JPEG_LIB_VERSION >= 70 +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED) +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +#endif +JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker") +#if JPEG_LIB_VERSION < 70 +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +#endif +JMESSAGE(JERR_BAD_RESTART, + "Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT3(cinfo, code, p1, p2, p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) +#define ERREXITS(cinfo, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX - 1), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS1(cinfo, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) +#define WARNMS2(cinfo, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo, lvl, code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS1(cinfo, lvl, code, p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS2(cinfo, lvl, code, p1, p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) +#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \ + MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); ) +#define TRACEMSS(cinfo, lvl, code, str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \ + (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/jmorecfg.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jmorecfg.h new file mode 100644 index 0000000..a4df71c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jmorecfg.h @@ -0,0 +1,389 @@ +/* + * jmorecfg.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, 2026, + * D. R. Commander. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255. + * However, darn few applications need more than 4 channels (maybe 5 for CMYK + + * alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +/* JSAMPLE should be the smallest type that will hold the values 0..255. */ + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int)(value)) + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + + +/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */ + +typedef short J12SAMPLE; + +#define MAXJ12SAMPLE 4095 +#define CENTERJ12SAMPLE 2048 + + +/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */ + +typedef unsigned short J16SAMPLE; + +#define MAXJ16SAMPLE 65535 +#define CENTERJ16SAMPLE 32768 + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +typedef unsigned char UINT8; + +/* UINT16 must hold at least the values 0..65535. */ + +typedef unsigned short UINT16; + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. + * + * NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were + * sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to + * long. It also wasn't common (or at least as common) in 1994 for INT32 to be + * defined by platform headers. Since then, however, INT32 is defined in + * several other common places: + * + * Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on + * 32-bit platforms (i.e always a 32-bit signed type.) + * + * basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type + * on modern platforms.) + * + * qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on + * modern platforms.) + * + * This is a recipe for conflict, since "long" and "int" aren't always + * compatible types. Since the definition of INT32 has technically been part + * of the libjpeg API for more than 20 years, we can't remove it, but we do not + * use it internally any longer. We instead define a separate type (JLONG) + * for internal use, which ensures that internal behavior will always be the + * same regardless of any external headers that may be included. + */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. (Note that changing this datatype will + * potentially require modifying the SIMD code. The x86-64 SIMD extensions, + * in particular, assume a 32-bit JDIMENSION.) + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JMETHOD(type, methodname, arglist) type (*methodname) arglist + + +/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS), + * but again, some software relies on this macro. + */ + +#undef FAR +#define FAR + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* accurate integer method */ +#define DCT_IFAST_SUPPORTED /* less accurate int method [legacy feature] */ +#define DCT_FLOAT_SUPPORTED /* floating-point method [legacy feature] */ + +/* Encoder capability options: */ + +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + C_MULTISCAN_FILES_SUPPORTED and + ENTROPY_OPT_SUPPORTED) */ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for lossless JPEG: the default tables don't + * work for lossless mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? (Requires + D_MULTISCAN_FILES_SUPPORTED) */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires + DCT_ISLOW_SUPPORTED) */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial + * feature of libjpeg. The idea was that, if an application developer needed + * to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could + * change these macros, rebuild libjpeg, and link their application statically + * with it. In reality, few people ever did this, because there were some + * severe restrictions involved (cjpeg and djpeg no longer worked properly, + * compressing/decompressing RGB JPEGs no longer worked properly, and the color + * quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since + * all of the O/S-supplied versions of libjpeg were built with the default + * values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications + * have come to regard these values as immutable. + * + * The libjpeg-turbo colorspace extensions provide a much cleaner way of + * compressing from/decompressing to buffers with arbitrary component orders + * and pixel sizes. Thus, we do not support changing the values of RGB_RED, + * RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions + * listed above, changing these values will also break the SIMD extensions and + * the regression tests. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + +#define JPEG_NUMCS 17 + +#define EXT_RGB_RED 0 +#define EXT_RGB_GREEN 1 +#define EXT_RGB_BLUE 2 +#define EXT_RGB_PIXELSIZE 3 + +#define EXT_RGBX_RED 0 +#define EXT_RGBX_GREEN 1 +#define EXT_RGBX_BLUE 2 +#define EXT_RGBX_PIXELSIZE 4 + +#define EXT_BGR_RED 2 +#define EXT_BGR_GREEN 1 +#define EXT_BGR_BLUE 0 +#define EXT_BGR_PIXELSIZE 3 + +#define EXT_BGRX_RED 2 +#define EXT_BGRX_GREEN 1 +#define EXT_BGRX_BLUE 0 +#define EXT_BGRX_PIXELSIZE 4 + +#define EXT_XBGR_RED 3 +#define EXT_XBGR_GREEN 2 +#define EXT_XBGR_BLUE 1 +#define EXT_XBGR_PIXELSIZE 4 + +#define EXT_XRGB_RED 1 +#define EXT_XRGB_GREEN 2 +#define EXT_XRGB_BLUE 3 +#define EXT_XRGB_PIXELSIZE 4 + +static const int rgb_red[JPEG_NUMCS] = { + -1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED, + EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED, + -1 +}; + +static const int rgb_green[JPEG_NUMCS] = { + -1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN, + EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN, + -1 +}; + +static const int rgb_blue[JPEG_NUMCS] = { + -1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE, + EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE, + -1 +}; + +static const int rgb_pixelsize[JPEG_NUMCS] = { + -1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE, + EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE, + -1 +}; + +/* Definitions for speed-related optimizations. */ + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#ifndef WITH_SIMD +#define MULTIPLIER int /* type for fastest integer multiply */ +#else +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +#endif +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + */ + +#ifndef FAST_FLOAT +#define FAST_FLOAT float +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/jpeglib.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jpeglib.h new file mode 100644 index 0000000..f7076a1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/jpeglib.h @@ -0,0 +1,1223 @@ +/* + * jpeglib.h + * + * This file was part of the Independent JPEG Group's software: + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. + * Lossless JPEG Modifications: + * Copyright (C) 1999, Ken Murchison. + * libjpeg-turbo Modifications: + * Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, 2022-2024, + D. R. Commander. + * Copyright (C) 2015, Google, Inc. + * For conditions of distribution and use, see the accompanying README.ijg + * file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +/* NOTE: This header file does not include stdio.h, despite the fact that it + * uses FILE and size_t. That is by design, since the libjpeg API predates the + * widespread adoption of ANSI/ISO C. Referring to libjpeg.txt, it is a + * documented requirement that calling programs "include system headers that + * define at least the typedefs FILE and size_t" before including jpeglib.h. + * Technically speaking, changing that requirement by including stdio.h here + * would break backward API compatibility. Please do not file bug reports, + * feature requests, or pull requests regarding this. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +/* NOTE: In lossless mode, an MCU contains one or more samples rather than one + * or more 8x8 DCT blocks, so the term "data unit" is used to generically + * describe a sample in lossless mode or an 8x8 DCT block in lossy mode. To + * preserve backward API/ABI compatibility, the field and macro names retain + * the "block" terminology. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + */ + +typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples with + 2-bit through 8-bit data precision. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some JSAMPLE rows (a 2-D JSAMPLE + array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D JSAMPLE array: top index is color */ + +typedef J12SAMPLE *J12SAMPROW; /* ptr to one image row of pixel samples + with 9-bit through 12-bit data + precision. */ +typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some J12SAMPLE rows (a 2-D + J12SAMPLE array) */ +typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D J12SAMPLE array: top index is + color */ + +typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of pixel samples + with 13-bit through 16-bit data + precision. */ +typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some J16SAMPLE rows (a 2-D + J16SAMPLE array) */ +typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D J16SAMPLE array: top index is + color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * In lossy mode, any dummy blocks added to complete an MCU are not counted; + * therefore these values do not depend on whether a scan is interleaved or + * not. In lossless mode, these are always equal to the image width and + * height. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a data unit in samples. Always DCTSIZE for lossy compression. + * For lossy decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values from 1 to 16 are supported. Note that different components may + * receive different IDCT scalings. In lossless mode, this is always equal + * to 1. + */ +#if JPEG_LIB_VERSION >= 70 + int DCT_h_scaled_size; + int DCT_v_scaled_size; +#else + int DCT_scaled_size; +#endif + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For lossy decompression, IDCT scaling is + * included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) + * In lossless mode, these are always equal to the image width and height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ + int last_col_width; /* # of non-dummy data units across in last MCU */ + int last_row_height; /* # of non-dummy data units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL *quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void *dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + (Ss is the predictor selection value in + lossless mode) */ + int Ah, Al; /* progressive JPEG successive approx. parms + (Al is the point transform value in lossless + mode) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct *jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET *data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +#define JCS_EXTENSIONS 1 +#define JCS_ALPHA_EXTENSIONS 1 + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue as specified by the RGB_RED, + RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_EXT_RGB, /* red/green/blue */ + JCS_EXT_RGBX, /* red/green/blue/x */ + JCS_EXT_BGR, /* blue/green/red */ + JCS_EXT_BGRX, /* blue/green/red/x */ + JCS_EXT_XBGR, /* x/blue/green/red */ + JCS_EXT_XRGB, /* x/red/green/blue */ + /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, + or JCS_EXT_XRGB during decompression, the X byte is undefined, and in + order to ensure the best performance, libjpeg-turbo can set that byte to + whatever value it wishes. Use the following colorspace constants to + ensure that the X byte is set to 0xFF, so that it can be interpreted as an + opaque alpha channel. */ + JCS_EXT_RGBA, /* red/green/blue/alpha */ + JCS_EXT_BGRA, /* blue/green/red/alpha */ + JCS_EXT_ABGR, /* alpha/blue/green/red */ + JCS_EXT_ARGB, /* alpha/red/green/blue */ + JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue + [decompression only] */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* accurate integer method */ + JDCT_IFAST, /* less accurate integer method [legacy feature] */ + JDCT_FLOAT /* floating-point method [legacy feature] */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr *err; /* Error handler module */ \ + struct jpeg_memory_mgr *mem; /* Memory manager module */ \ + struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \ + void *client_data; /* Available for use by application */ \ + boolean is_decompressor; /* So common code can tell which is which */ \ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct *j_common_ptr; +typedef struct jpeg_compress_struct *j_compress_ptr; +typedef struct jpeg_decompress_struct *j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr *dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + +#if JPEG_LIB_VERSION >= 70 + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ +#endif + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; +#if JPEG_LIB_VERSION >= 70 + int q_scale_factor[NUM_QUANT_TBLS]; +#endif + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info *scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ +#if JPEG_LIB_VERSION >= 70 + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ +#endif + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coefficient or + difference controller */ + /* The coefficient or difference controller receives data in units of MCU + * rows as defined for fully interleaved scans (whether the JPEG file is + * interleaved or not). In lossy mode, there are v_samp_factor * DCTSIZE + * sample rows of each component in an "iMCU" (interleaved MCU) row. In + * lossless mode, total_iMCU_rows is always equal to the image height. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ +#endif + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master *master; + struct jpeg_c_main_controller *main; + struct jpeg_c_prep_controller *prep; + struct jpeg_c_coef_controller *coef; + struct jpeg_marker_writer *marker; + struct jpeg_color_converter *cconvert; + struct jpeg_downsampler *downsample; + struct jpeg_forward_dct *fdct; + struct jpeg_entropy_encoder *entropy; + jpeg_scan_info *script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr *src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array + If data_precision is 12, then this is + actually a J12SAMPARRAY, so callers must + type-cast it in order to read/write 12-bit + samples from/to the array. */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL *quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info *comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + +#if JPEG_LIB_VERSION >= 80 + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ +#endif + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + +#if JPEG_LIB_VERSION >= 70 + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ +#else + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ +#endif + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient or difference controller's input and output progress is + * measured in units of "iMCU" (interleaved MCU) rows. These are the same as + * MCU rows in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. In lossy mode, we define an iMCU row as v_samp_factor + * DCT block rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_[v_]scaled_size sample rows of a component per iMCU row. + * In lossless mode, total_iMCU_rows is always equal to the image height. + */ + + JSAMPLE *sample_range_limit; /* table for fast range-limiting + If data_precision is 9 to 12, then this is + actually a J12SAMPLE pointer, and if + data_precision is 13 to 16, then this is + actually a J16SAMPLE pointer, so callers + must type-cast it in order to read samples + from the array. */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info *cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of data units per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for + scan */ + +#if JPEG_LIB_VERSION >= 80 + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int *natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ +#endif + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master *master; + struct jpeg_d_main_controller *main; + struct jpeg_d_coef_controller *coef; + struct jpeg_d_post_controller *post; + struct jpeg_input_controller *inputctl; + struct jpeg_marker_reader *marker; + struct jpeg_entropy_decoder *entropy; + struct jpeg_inverse_dct *idct; + struct jpeg_upsampler *upsample; + struct jpeg_color_deconverter *cconvert; + struct jpeg_color_quantizer *cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + void (*error_exit) (j_common_ptr cinfo); + /* Conditionally emit a trace or warning message */ + void (*emit_message) (j_common_ptr cinfo, int msg_level); + /* Routine that actually outputs a trace or error message */ + void (*output_message) (j_common_ptr cinfo); + /* Format a message string for the most recent JPEG error or message */ + void (*format_message) (j_common_ptr cinfo, char *buffer); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + void (*reset_error_mgr) (j_common_ptr cinfo); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const *jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const *addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + void (*progress_monitor) (j_common_ptr cinfo); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET *next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + void (*init_destination) (j_compress_ptr cinfo); + boolean (*empty_output_buffer) (j_compress_ptr cinfo); + void (*term_destination) (j_compress_ptr cinfo); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET *next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + void (*init_source) (j_decompress_ptr cinfo); + boolean (*fill_input_buffer) (j_decompress_ptr cinfo); + void (*skip_input_data) (j_decompress_ptr cinfo, long num_bytes); + boolean (*resync_to_restart) (j_decompress_ptr cinfo, int desired); + void (*term_source) (j_decompress_ptr cinfo); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control *jvirt_sarray_ptr; +typedef struct jvirt_barray_control *jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); + void *(*alloc_large) (j_common_ptr cinfo, int pool_id, + size_t sizeofobject); + /* If cinfo->data_precision is 12 or 16, then this method and the + * access_virt_sarray method actually return a J12SAMPARRAY or a + * J16SAMPARRAY, so callers must type-cast the return value in order to + * read/write 12-bit or 16-bit samples from/to the array. + */ + JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows); + JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows); + jvirt_sarray_ptr (*request_virt_sarray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + jvirt_barray_ptr (*request_virt_barray) (j_common_ptr cinfo, int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess); + void (*realize_virt_arrays) (j_common_ptr cinfo); + JSAMPARRAY (*access_virt_sarray) (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + JBLOCKARRAY (*access_virt_barray) (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable); + void (*free_pool) (j_common_ptr cinfo, int pool_id); + void (*self_destruct) (j_common_ptr cinfo); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef boolean (*jpeg_marker_parser_method) (j_decompress_ptr cinfo); + + +/* Originally, this macro was used as a way of defining function prototypes + * for both modern compilers as well as older compilers that did not support + * prototype parameters. libjpeg-turbo has never supported these older, + * non-ANSI compilers, but the macro is still included because there is some + * software out there that uses it. + */ + +#define JPP(arglist) arglist + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t)sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version, + size_t structsize); +EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, + size_t structsize); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile); +EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer, + unsigned long *outsize); +EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, + const unsigned char *inbuffer, unsigned long insize); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo, + J_COLOR_SPACE colorspace); +EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo); +EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality, + boolean force_baseline); +EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor, + boolean force_baseline); +#if JPEG_LIB_VERSION >= 70 +EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo, + boolean force_baseline); +#endif +EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline); +EXTERN(int) jpeg_quality_scaling(int quality); +EXTERN(void) jpeg_enable_lossless(j_compress_ptr cinfo, + int predictor_selection_value, + int point_transform); +EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo); +EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo, + boolean write_all_tables); +EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION num_lines); +EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); + +#if JPEG_LIB_VERSION >= 70 +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo); +#endif + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_write_raw_data(j_compress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION num_lines); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker, + unsigned int datalen); +EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo); + +/* Write ICC profile. See libjpeg.txt for usage information. */ +EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len); + + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo); +EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, + J12SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo, + J16SAMPARRAY scanlines, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, + JDIMENSION num_lines); +EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(void) jpeg12_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, + JDIMENSION *width); +EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines); +EXTERN(JDIMENSION) jpeg12_read_raw_data(j_decompress_ptr cinfo, + J12SAMPIMAGE data, + JDIMENSION max_lines); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number); +EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo); +EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo); +EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo); +EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +#if JPEG_LIB_VERSION >= 80 +EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo); +#endif +EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo, + int marker_code, + jpeg_marker_parser_method routine); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo); +EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo, + jvirt_barray_ptr *coef_arrays); +EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, + j_compress_ptr dstinfo); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo); +EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort(j_common_ptr cinfo); +EXTERN(void) jpeg_destroy(j_common_ptr cinfo); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired); + +/* Read ICC profile. See libjpeg.txt for usage information. */ +EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Buffer.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Buffer.hh new file mode 100644 index 0000000..eaa84c9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Buffer.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef BUFFER_HH +#define BUFFER_HH + +#include + +#include +#include +#include +#include + +class Buffer +{ + public: + QPDF_DLL + Buffer(); + + // Create a Buffer object whose memory is owned by the class and will be freed when the Buffer + // object is destroyed. + QPDF_DLL + Buffer(size_t size); + QPDF_DLL + Buffer(std::string&& content); + + // Create a Buffer object whose memory is owned by the caller and will not be freed when the + // Buffer is destroyed. + QPDF_DLL + Buffer(unsigned char* buf, size_t size); + QPDF_DLL + Buffer(std::string& content); + + Buffer(Buffer const&) = delete; + Buffer& operator=(Buffer const&) = delete; + + QPDF_DLL + Buffer(Buffer&&) noexcept; + QPDF_DLL + Buffer& operator=(Buffer&&) noexcept; + QPDF_DLL + ~Buffer(); + QPDF_DLL + size_t getSize() const; + QPDF_DLL + unsigned char const* getBuffer() const; + QPDF_DLL + unsigned char* getBuffer(); + + // Create a new copy of the Buffer. The new Buffer owns an independent copy of the data. + QPDF_DLL + Buffer copy() const; + + // Move the content of the Buffer. After calling this method, the Buffer will be empty if the + // buffer owns its memory. Otherwise, the Buffer will be unchanged. + QPDF_DLL + std::string move(); + + // Return a string_view to the data. + QPDF_DLL + std::string_view view() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char const* data() const; + + // Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even + // if the Buffer is empty. + QPDF_DLL + char* data(); + + QPDF_DLL + bool empty() const; + + QPDF_DLL + size_t size() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/BufferInputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/BufferInputSource.hh new file mode 100644 index 0000000..0b857b8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/BufferInputSource.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_BUFFERINPUTSOURCE_HH +#define QPDF_BUFFERINPUTSOURCE_HH + +#include +#include + +#include + +class QPDF_DLL_CLASS BufferInputSource: public InputSource +{ + public: + // If own_memory is true, BufferInputSource will delete the buffer when finished with it. + // Otherwise, the caller owns the memory. + QPDF_DLL + BufferInputSource(std::string const& description, Buffer* buf, bool own_memory = false); + + // NB This overload copies the string contents. + QPDF_DLL + BufferInputSource(std::string const& description, std::string const& contents); + QPDF_DLL + ~BufferInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: +#ifndef QPDF_FUTURE + bool own_memory; + std::string description; + Buffer* buf; + qpdf_offset_t cur_offset; + qpdf_offset_t max_offset; +#else + class Members; + + std::unique_ptr m; +#endif +}; + +#endif // QPDF_BUFFERINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/ClosedFileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/ClosedFileInputSource.hh new file mode 100644 index 0000000..56b2cb1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/ClosedFileInputSource.hh @@ -0,0 +1,77 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_CLOSEDFILEINPUTSOURCE_HH +#define QPDF_CLOSEDFILEINPUTSOURCE_HH + +#include + +#include + +class FileInputSource; + +// This is an input source that reads from files, like FileInputSource, except that it opens and +// closes the file surrounding every operation. This decreases efficiency, but it allows many more +// of these to exist at once than the maximum number of open file descriptors. This is used for +// merging large numbers of files. +class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource +{ + public: + QPDF_DLL + ClosedFileInputSource(char const* filename); + + ClosedFileInputSource(ClosedFileInputSource const&) = delete; + ClosedFileInputSource& operator=(ClosedFileInputSource const&) = delete; + + QPDF_DLL + ~ClosedFileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + // The file stays open between calls to stayOpen(true) and stayOpen(false). You can use this to + // surround multiple operations on a single ClosedFileInputSource to reduce the overhead of a + // separate open/close on each call. + QPDF_DLL + void stayOpen(bool); + + private: + QPDF_DLL_PRIVATE + void before(); + QPDF_DLL_PRIVATE + void after(); + + std::string filename; + qpdf_offset_t offset{0}; + std::shared_ptr fis; + bool stay_open{false}; +}; + +#endif // QPDF_CLOSEDFILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Constants.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Constants.h new file mode 100644 index 0000000..4b32713 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Constants.h @@ -0,0 +1,297 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFCONSTANTS_H +#define QPDFCONSTANTS_H + +/* + * REMEMBER: + * + * Keep this file 'C' compatible so it can be used from the C and C++ + * interfaces. + */ + +/* ****************************** NOTE ****************************** + +Tl;Dr: new values must be added to the end such that no constant's +numerical value changes, even across major releases. + +Details: + +As new values are added to existing enumerated types in this file, +it is important not to change the actual values of any constants. +This means that, in the absence of explicit assignment of values, +the order of entries can't change even across major releases. Why? +Here are the reasons: + +* Many of these constants are used by the C API. The C API is used + through foreign function call interfaces by users of other languages + who may not have access to or the ability to parse a C header file. + As such, users are likely to hard-code numerical values or create + their own constants whose values match. If we change values here, + their code would break, and there would be no way to detect it short + of noticing a bug. Furthermore, it would be difficult to write code + that properly handled more than one version of the qpdf shared + object (e.g. DLL) since the information about what version of qpdf + is involved is only available at runtime. + +- It has happened from time to time that a user builds an application + with an incorrectly installed qpdf, such as having mismatched header + files and library files. In the event that they are only using qpdf + interfaces that have been stable across the versions in question, + this turns out to be harmless. If they happen to use non-compatible + interfaces, this results usually in a failure to load or an obvious + runtime error. If we change values of constants, it is possible that + code that links and runs may have mismatched values for constants. + This would create a bug that would be extremely difficult to track + down and impossible for qpdf maintainers to reproduce. + +*/ + +/* Exit Codes from QPDFJob and the qpdf CLI */ + +enum qpdf_exit_code_e { + qpdf_exit_success = 0, + /* Normal exit codes */ + qpdf_exit_error = 2, + qpdf_exit_warning = 3, + /* For --is-encrypted and --requires-password */ + qpdf_exit_is_not_encrypted = 2, + qpdf_exit_correct_password = 3, +}; + +/* Error Codes */ + +enum qpdf_error_code_e { + qpdf_e_success = 0, + qpdf_e_internal, /* logic/programming error -- indicates bug */ + qpdf_e_system, /* I/O error, memory error, etc. */ + qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */ + qpdf_e_password, /* incorrect password for encrypted file */ + qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */ + qpdf_e_pages, /* erroneous or unsupported pages structure */ + qpdf_e_object, /* type/bounds errors accessing objects */ + qpdf_e_json, /* error in qpdf JSON */ + qpdf_e_linearization, /* linearization warning */ +}; + +/* Object Types */ + +/* PDF objects represented by QPDFObjectHandle or, in the C API, by + * qpdf_oh, have a unique type code that has one of the values in the + * list below. As new object types are added to qpdf, additional items + * may be added to the list, so code that switches on these values + * should take that into consideration. (Maintainer note: it would be + * better to call this qpdf_ot_* rather than ot_* to reduce likelihood + * of name collision, but changing the names of the values breaks + * backward compatibility.) + */ +enum qpdf_object_type_e { + /* Object types internal to qpdf */ + ot_uninitialized, + ot_reserved, + /* Object types that can occur in the main document */ + ot_null, + ot_boolean, + ot_integer, + ot_real, + ot_string, + ot_name, + ot_array, + ot_dictionary, + ot_stream, + /* Additional object types that can occur in content streams */ + ot_operator, + ot_inlineimage, + /* Object types internal to qpdf */ + ot_unresolved, + ot_destroyed, + ot_reference, +}; + +/* Write Parameters. See QPDFWriter.hh for details. */ + +enum qpdf_object_stream_e { + qpdf_o_disable = 0, /* disable object streams */ + qpdf_o_preserve, /* preserve object streams */ + qpdf_o_generate /* generate object streams */ +}; +enum qpdf_stream_data_e { + qpdf_s_uncompress = 0, /* uncompress stream data */ + qpdf_s_preserve, /* preserve stream data compression */ + qpdf_s_compress /* compress stream data */ +}; + +/* Stream data flags */ + +/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */ +enum qpdf_stream_encode_flags_e { + qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */ + qpdf_ef_normalize = 1 << 1, /* normalize content stream */ +}; +enum qpdf_stream_decode_level_e { + /* These must be in order from less to more decoding. */ + qpdf_dl_none = 0, /* preserve all stream filters */ + qpdf_dl_generalized, /* decode general-purpose filters */ + qpdf_dl_specialized, /* also decode other non-lossy filters */ + qpdf_dl_all /* also decode lossy filters */ +}; +/* For JSON encoding */ +enum qpdf_json_stream_data_e { + qpdf_sj_none = 0, + qpdf_sj_inline, + qpdf_sj_file, +}; + +/* R3 Encryption Parameters */ + +enum qpdf_r3_print_e { + qpdf_r3p_full = 0, /* allow all printing */ + qpdf_r3p_low, /* allow only low-resolution printing */ + qpdf_r3p_none /* allow no printing */ +}; + +/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It + * corresponds to options in Acrobat 5's menus. The new interface in + * QPDFWriter offers more granularity and no longer uses this type. + */ +enum qpdf_r3_modify_e /* Allowed changes: */ +{ + qpdf_r3m_all = 0, /* All editing */ + qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */ + qpdf_r3m_form, /* Fill forms, signing, assembly */ + qpdf_r3m_assembly, /* Only document assembly */ + qpdf_r3m_none /* No modifications */ +}; + +/* Form field flags from the PDF spec */ + +enum pdf_form_field_flag_e { + /* flags that apply to all form fields */ + ff_all_read_only = 1 << 0, + ff_all_required = 1 << 1, + ff_all_no_export = 1 << 2, + + /* flags that apply to fields of type /Btn (button) */ + ff_btn_no_toggle_off = 1 << 14, + ff_btn_radio = 1 << 15, + ff_btn_pushbutton = 1 << 16, + ff_btn_radios_in_unison = 1 << 17, + + /* flags that apply to fields of type /Tx (text) */ + ff_tx_multiline = 1 << 12, + ff_tx_password = 1 << 13, + ff_tx_file_select = 1 << 20, + ff_tx_do_not_spell_check = 1 << 22, + ff_tx_do_not_scroll = 1 << 23, + ff_tx_comb = 1 << 24, + ff_tx_rich_text = 1 << 25, + + /* flags that apply to fields of type /Ch (choice) */ + ff_ch_combo = 1 << 17, + ff_ch_edit = 1 << 18, + ff_ch_sort = 1 << 19, + ff_ch_multi_select = 1 << 21, + ff_ch_do_not_spell_check = 1 << 22, + ff_ch_commit_on_sel_change = 1 << 26 +}; + +/* Annotation flags from the PDF spec */ + +enum pdf_annotation_flag_e { + an_invisible = 1 << 0, + an_hidden = 1 << 1, + an_print = 1 << 2, + an_no_zoom = 1 << 3, + an_no_rotate = 1 << 4, + an_no_view = 1 << 5, + an_read_only = 1 << 6, + an_locked = 1 << 7, + an_toggle_no_view = 1 << 8, + an_locked_contents = 1 << 9 +}; + +/* Encryption/password status for QPDFJob */ +enum qpdf_encryption_status_e { qpdf_es_encrypted = 1 << 0, qpdf_es_password_incorrect = 1 << 1 }; + +/* Page label types */ +enum qpdf_page_label_e { + pl_none, + pl_digits, + pl_alpha_lower, + pl_alpha_upper, + pl_roman_lower, + pl_roman_upper, +}; + +/** + * @enum qpdf_result_e + * @brief Enum representing result codes for qpdf C-API functions. + * + * Results <= qpdf_r_no_warn indicate success without warnings, + * qpdf_r_no_warn < result <= qpdf_r_success indicates success with warnings, and + * qpdf_r_success < result indicates failure. + */ +enum qpdf_result_e { + /* success */ + qpdf_r_ok = 0, + qpdf_r_no_warn = 0xff, /// any result <= qpdf_no_warn indicates success without warning + qpdf_r_success = 0xffff, /// any result <= qpdf_r_success indicates success + /* failure */ + qpdf_r_bad_parameter = 0x10000, + + qpdf_r_no_warn_mask = 0x7fffff00, + qpdf_r_success_mask = 0x7fff0000, +}; + +/** + * @enum qpdf_param_e + * @brief This enumeration defines various parameters and configuration options for qpdf C-API + * functions. + * + * The enum values are grouped into sections based on their functionality, such as global + * options or global limits. For the meaning of individual parameters see `qpdf/global.cc` + */ +enum qpdf_param_e { + /* global state */ + qpdf_p_limit_errors = 0x10020, + + /* global options */ + qpdf_p_inspection_mode = 0x11000, + qpdf_p_default_limits = 0x11100, + /* global limits */ + + /* parser limits */ + qpdf_p_parser_max_nesting = 0x13000, + qpdf_p_parser_max_errors, + qpdf_p_parser_max_container_size, + qpdf_p_parser_max_container_size_damaged, + + /* stream and filter limits */ + qpdf_p_max_stream_filters = 0x14000, + + /* next section = 0x20000 */ + qpdf_enum_max = 0x7fffffff, +}; + +#endif /* QPDFCONSTANTS_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/DLL.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/DLL.h new file mode 100644 index 0000000..cc6dcbb --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/DLL.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDF_DLL_HH +#define QPDF_DLL_HH + +/* The first version of qpdf to include the version constants is 10.6.0. */ +#define QPDF_MAJOR_VERSION 12 +#define QPDF_MINOR_VERSION 3 +#define QPDF_PATCH_VERSION 2 + +#ifdef QPDF_FUTURE +# define QPDF_VERSION "12.3.2+future" +#else +# define QPDF_VERSION "12.3.2" +#endif + +/* + * This file defines symbols that control the which functions, + * classes, and methods are exposed to the public ABI (application + * binary interface). See below for a detailed explanation. + */ + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef libqpdf_EXPORTS +# define QPDF_DLL __declspec(dllexport) +# else +# define QPDF_DLL +# endif +# define QPDF_DLL_PRIVATE +#elif defined __GNUC__ +# define QPDF_DLL __attribute__((visibility("default"))) +# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden"))) +#else +# define QPDF_DLL +# define QPDF_DLL_PRIVATE +#endif +#ifdef __GNUC__ +# define QPDF_DLL_CLASS QPDF_DLL +#else +# define QPDF_DLL_CLASS +#endif + +/* + +Here's what's happening. See also https://gcc.gnu.org/wiki/Visibility +for a more in-depth discussion. + +* Everything in the public ABI must be exported. Things not in the + public ABI should not be exported. + +* A class's runtime type information is need if the class is going to + be used as an exception, inherited from, or tested with + dynamic_class. To do these things across a shared object boundary, + runtime type information must be exported. + +* On Windows: + + * For a symbol (function, method, etc.) to be exported into the + public ABI, it must be explicitly marked for export. + + * If you mark a class for export, all symbols in the class, + including private methods, are exported into the DLL, and there is + no way to exclude something from export. + + * A class's run-time type information is made available based on the + presence of a compiler flag (with MSVC), which is always on for + qpdf builds. + + * Marking classes for export should be done only when *building* the + DLL, not when *using* the DLL. + + * It is possible to mark symbols for import for DLL users, but it is + not necessary, and doing it right is complex in our case of being + multi-platform and building both static and shared libraries that + use the same headers, so we don't bother. + + * If we don't export base classes with mingw, the vtables don't end + up in the DLL. + +* On Linux (and other similar systems): + + * Common compilers such as gcc and clang export all symbols into the + public ABI by default. The qpdf build overrides this by using + "visibility=hidden", which makes it behave more like Windows in + that things have to be explicitly exported to appear in the public + ABI. + + * As with Windows, marking a class for export causes everything in + the class, including private methods, the be exported. However, + unlike in Windows: + + * It is possible to explicitly mark symbols as private + + * The only way to get the runtime type and vtable information into + the ABI is to mark the class as exported. + + * It is harmless and sometimes necessary to include the visibility + marks when using the library as well as when building it. In + particular, clang on MacOS requires the visibility marks to + match in both cases. + +What does this mean: + +* On Windows, we never have to export a class, and while there is no + way to "unexport" something, we also have no need to do it. + +* On non-Windows, we have to export some classes, and when we do, we + have to "unexport" some of their parts. + +* We only use the libqpdf_EXPORTS as a conditional for defining the + symbols for Windows builds. + +To achieve this, we use QPDF_DLL_CLASS to export classes, QPDF_DLL to +export methods, and QPDF_DLL_PRIVATE to unexport private methods in +exported classes. + +*/ + +#endif /* QPDF_DLL_HH */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/FileInputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/FileInputSource.hh new file mode 100644 index 0000000..af42400 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/FileInputSource.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_FILEINPUTSOURCE_HH +#define QPDF_FILEINPUTSOURCE_HH + +#include + +class QPDF_DLL_CLASS FileInputSource: public InputSource +{ + public: + FileInputSource() = default; + QPDF_DLL + FileInputSource(char const* filename); + QPDF_DLL + FileInputSource(char const* description, FILE* filep, bool close_file); + QPDF_DLL + void setFilename(char const* filename); + QPDF_DLL + void setFile(char const* description, FILE* filep, bool close_file); + + FileInputSource(FileInputSource const&) = delete; + FileInputSource& operator=(FileInputSource const&) = delete; + + QPDF_DLL + ~FileInputSource() override; + QPDF_DLL + qpdf_offset_t findAndSkipNextEOL() override; + QPDF_DLL + std::string const& getName() const override; + QPDF_DLL + qpdf_offset_t tell() override; + QPDF_DLL + void seek(qpdf_offset_t offset, int whence) override; + QPDF_DLL + void rewind() override; + QPDF_DLL + size_t read(char* buffer, size_t length) override; + QPDF_DLL + void unreadCh(char ch) override; + + private: + bool close_file{false}; + std::string filename; + FILE* file{nullptr}; +}; + +#endif // QPDF_FILEINPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/InputSource.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/InputSource.hh new file mode 100644 index 0000000..bac54ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/InputSource.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_INPUTSOURCE_HH +#define QPDF_INPUTSOURCE_HH + +#include +#include + +#include +#include +#include + +// Remember to use QPDF_DLL_CLASS on anything derived from InputSource so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS InputSource +{ + public: + InputSource() = default; + + virtual ~InputSource() = default; + + class QPDF_DLL_CLASS Finder + { + public: + QPDF_DLL + Finder() = default; + QPDF_DLL + virtual ~Finder() = default; + virtual bool check() = 0; + }; + + QPDF_DLL + void setLastOffset(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getLastOffset() const; + QPDF_DLL + std::string readLine(size_t max_line_length); + + // Find first or last occurrence of a sequence of characters starting within the range defined + // by offset and len such that, when the input source is positioned at the beginning of that + // sequence, finder.check() returns true. If len is 0, the search proceeds until EOF. If a + // qualifying pattern is found, these methods return true and leave the input source positioned + // wherever check() left it at the end of the matching pattern. + QPDF_DLL + bool findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + QPDF_DLL + bool findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder); + + virtual qpdf_offset_t findAndSkipNextEOL() = 0; + virtual std::string const& getName() const = 0; + virtual qpdf_offset_t tell() = 0; + virtual void seek(qpdf_offset_t offset, int whence) = 0; + virtual void rewind() = 0; + virtual size_t read(char* buffer, size_t length) = 0; + + // Note: you can only unread the character you just read. The specific character is ignored by + // some implementations, and the implementation doesn't check this. Use of unreadCh is + // semantically equivalent to seek(-1, SEEK_CUR) but is much more efficient. + virtual void unreadCh(char ch) = 0; + + // The following methods are for internal use by qpdf only. + inline size_t read(std::string& str, size_t count, qpdf_offset_t at = -1); + inline std::string read(size_t count, qpdf_offset_t at = -1); + size_t read_line(std::string& str, size_t count, qpdf_offset_t at = -1); + std::string read_line(size_t count, qpdf_offset_t at = -1); + inline qpdf_offset_t fastTell(); + inline bool fastRead(char&); + inline void fastUnread(bool); + inline void loadBuffer(); + + protected: + qpdf_offset_t last_offset{0}; + + private: + // State for fast... methods + static const qpdf_offset_t buf_size = 128; + char buffer[buf_size]; + qpdf_offset_t buf_len = 0; + qpdf_offset_t buf_idx = 0; + qpdf_offset_t buf_start = 0; +}; + +#endif // QPDF_INPUTSOURCE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/JSON.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/JSON.hh new file mode 100644 index 0000000..3713e73 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/JSON.hh @@ -0,0 +1,404 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef JSON_HH +#define JSON_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Pipeline; +class InputSource; + +// This is a simple JSON serializer and parser, primarily designed for serializing QPDF Objects as +// JSON. While it may work as a general-purpose JSON parser/serializer, there are better options. +// JSON objects contain their data as smart pointers. When one JSON object is added to another, this +// pointer is copied. This means you can create temporary JSON objects on the stack, add them to +// other objects, and let them go out of scope safely. It also means that if a JSON object is added +// in more than one place, all copies share the underlying data. This makes them similar in +// structure and behavior to QPDFObjectHandle and may feel natural within the QPDF codebase, but it +// is also a good reason not to use this as a general-purpose JSON package. +class JSON +{ + public: + static int constexpr LATEST = 2; + + JSON() = default; + + QPDF_DLL + std::string unparse() const; + + // Write the JSON object through a pipeline. The `depth` parameter specifies how deeply nested + // this is in another JSON structure, which makes it possible to write clean-looking JSON + // incrementally. + QPDF_DLL + void write(Pipeline*, size_t depth = 0) const; + + // Helper methods for writing JSON incrementally. + // + // "first" -- Several methods take a `bool& first` parameter. The open methods always set it to + // true, and the methods to output items always set it to false. This way, the item and close + // methods can always know whether or not a first item is being written. The intended mode of + // operation is to start with a new `bool first = true` each time a new container is opened and + // to pass that `first` through to all the methods that are called to add top-level items to the + // container as well as to close the container. This lets the JSON object use it to keep track + // of when it's writing a first object and when it's not. If incrementally writing multiple + // levels of depth, a new `first` should be used for each new container that is opened. + // + // "depth" -- Indicate the level of depth. This is used for consistent indentation. When writing + // incrementally, whenever you call a method to add an item to a container, the value of `depth` + // should be one more than whatever value is passed to the container open and close methods. + + // Open methods ignore the value of first and set it to false + QPDF_DLL + static void writeDictionaryOpen(Pipeline*, bool& first, size_t depth = 0); + QPDF_DLL + static void writeArrayOpen(Pipeline*, bool& first, size_t depth = 0); + // Close methods don't modify first. A true value indicates that we are closing an empty object. + QPDF_DLL + static void writeDictionaryClose(Pipeline*, bool first, size_t depth = 0); + QPDF_DLL + static void writeArrayClose(Pipeline*, bool first, size_t depth = 0); + // The item methods use the value of first to determine if this is the first item and always set + // it to false. + QPDF_DLL + static void writeDictionaryItem( + Pipeline*, bool& first, std::string const& key, JSON const& value, size_t depth = 0); + // Write just the key of a new dictionary item, useful if writing nested structures. Calls + // writeNext. + QPDF_DLL + static void + writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth = 0); + QPDF_DLL + static void writeArrayItem(Pipeline*, bool& first, JSON const& element, size_t depth = 0); + // If writing nested structures incrementally, call writeNext before opening a new array or + // container in the midst of an existing one. The `first` you pass to writeNext should be the + // one for the parent object. The depth should be the one for the child object. Then start a new + // `first` for the nested item. Note that writeDictionaryKey and writeArrayItem call writeNext + // for you, so this is most important when writing subsequent items or container openers to an + // array. + QPDF_DLL + static void writeNext(Pipeline* p, bool& first, size_t depth = 0); + + // The JSON spec calls dictionaries "objects", but that creates too much confusion when + // referring to instances of the JSON class. + QPDF_DLL + static JSON makeDictionary(); + // addDictionaryMember returns the newly added item. + QPDF_DLL + JSON addDictionaryMember(std::string const& key, JSON const&); + QPDF_DLL + static JSON makeArray(); + // addArrayElement returns the newly added item. + QPDF_DLL + JSON addArrayElement(JSON const&); + QPDF_DLL + static JSON makeString(std::string const& utf8); + QPDF_DLL + static JSON makeInt(long long int value); + QPDF_DLL + static JSON makeReal(double value); + QPDF_DLL + static JSON makeNumber(std::string const& encoded); + QPDF_DLL + static JSON makeBool(bool value); + QPDF_DLL + static JSON makeNull(); + + // A blob serializes as a string. The function will be called by JSON with a pipeline and should + // write binary data to the pipeline but not call finish(). JSON will call finish() at the right + // time. + QPDF_DLL + static JSON makeBlob(std::function); + + QPDF_DLL + bool isArray() const; + + QPDF_DLL + bool isDictionary() const; + + // Accessors. Accessor behavior: + // + // - If argument is wrong type, including null, return false + // - If argument is right type, return true and initialize the value + + QPDF_DLL + bool getString(std::string& utf8) const; + QPDF_DLL + bool getNumber(std::string& value) const; + QPDF_DLL + bool getBool(bool& value) const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + JSON getDictItem(std::string const& key) const; + QPDF_DLL + bool forEachDictItem(std::function fn) const; + QPDF_DLL + bool forEachArrayItem(std::function fn) const; + + // Check this JSON object against a "schema". This is not a schema according to any standard. + // It's just a template of what the JSON is supposed to contain. The checking does the + // following: + // + // * The schema is a nested structure containing dictionaries, single-element arrays, and + // strings only. + // * Recursively walk the schema. In the items below, "schema object" refers to an object in + // the schema, and "checked object" refers to the corresponding part of the object being + // checked. + // * If the schema object is a dictionary, the checked object must have a dictionary in the + // same place with the same keys. If flags contains f_optional, a key in the schema does not + // have to be present in the object. Otherwise, all keys have to be present. Any key in the + // object must be present in the schema. + // * If the schema object is an array of length 1, the checked object may either be a single + // item or an array of items. The single item or each element of the checked object's + // array is validated against the single element of the schema's array. The rationale behind + // this logic is that a single element may appear wherever the schema allows a + // variable-length array. This makes it possible to start allowing an array in the future + // where a single element was previously required without breaking backward compatibility. + // * If the schema object is an array of length > 1, the checked object must be an array of + // the same length. In this case, each element of the checked object array is validated + // against the corresponding element of the schema array. + // * Otherwise, the value must be a string whose value is a description of the object's + // corresponding value, which may have any type. + // + // QPDF's JSON output conforms to certain strict compatibility rules as discussed in the manual. + // The idea is that a JSON structure created manually in qpdf.cc doubles as both JSON help + // information and a schema for validating the JSON that qpdf generates. Any discrepancies are a + // bug in qpdf. + // + // Flags is a bitwise or of values from check_flags_e. + enum check_flags_e { + f_none = 0, + f_optional = 1 << 0, + }; + QPDF_DLL + bool checkSchema(JSON schema, unsigned long flags, std::list& errors); + + // Same as passing 0 for flags + QPDF_DLL + bool checkSchema(JSON schema, std::list& errors); + + // A pointer to a Reactor class can be passed to parse, which will enable the caller to react + // to incremental events in the construction of the JSON object. This makes it possible to + // implement SAX-like handling of very large JSON objects. + class QPDF_DLL_CLASS Reactor + { + public: + virtual ~Reactor() = default; + + // The start/end methods are called when parsing of a dictionary or array is started or + // ended. The item methods are called when an item is added to a dictionary or array. When + // adding a container to another container, the item method is called with an empty + // container before the lower container's start method is called. See important notes in + // "Item methods" below. + + // During parsing of a JSON string, the parser is operating on a single object at a time. + // When a dictionary or array is started, a new context begins, and when that dictionary or + // array is ended, the previous context is resumed. So, for + // example, if you have `{"a": [1]}`, you will receive the + // following method calls + // + // dictionaryStart -- current object is the top-level dictionary + // dictionaryItem -- called with "a" and an empty array + // arrayStart -- current object is the array + // arrayItem -- called with the "1" object + // containerEnd -- now current object is the dictionary again + // containerEnd -- current object is undefined + // + // If the top-level item in a JSON string is a scalar, the topLevelScalar() method will be + // called. No argument is passed since the object is the same as what is returned by + // parse(). + + QPDF_DLL + virtual void dictionaryStart() = 0; + QPDF_DLL + virtual void arrayStart() = 0; + QPDF_DLL + virtual void containerEnd(JSON const& value) = 0; + QPDF_DLL + virtual void topLevelScalar() = 0; + + // Item methods: + // + // The return value of the item methods indicate whether the item has been "consumed". If + // the item method returns true, then the item will not be added to the containing JSON + // object. This is what allows arbitrarily large JSON objects + // to be parsed and not have to be kept in memory. + // + // NOTE: When a dictionary or an array is added to a container, the dictionaryItem or + // arrayItem method is called when the child item's start delimiter is encountered, so the + // JSON object passed in at that time will always be in its initial, empty state. + // Additionally, the child item's start method is not called until after the parent item's + // item method is called. This makes it possible to keep track of the current depth level by + // incrementing level on start methods and decrementing on end methods. + + QPDF_DLL + virtual bool dictionaryItem(std::string const& key, JSON const& value) = 0; + QPDF_DLL + virtual bool arrayItem(JSON const& value) = 0; + }; + + // Create a JSON object from a string. + QPDF_DLL + static JSON parse(std::string const&); + // Create a JSON object from an input source. See above for information about how to use the + // Reactor. + QPDF_DLL + static JSON parse(InputSource&, Reactor* reactor = nullptr); + + // parse calls setOffsets to set the inclusive start and non-inclusive end offsets of an object + // relative to its input string. Otherwise, both values are 0. + QPDF_DLL + void setStart(qpdf_offset_t); + QPDF_DLL + void setEnd(qpdf_offset_t); + QPDF_DLL + qpdf_offset_t getStart() const; + QPDF_DLL + qpdf_offset_t getEnd() const; + + // The following class does not form part of the public API and is for internal use only. + + class Writer; + + private: + static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter); + + enum value_type_e { + vt_none, + vt_dictionary, + vt_array, + vt_string, + vt_number, + vt_bool, + vt_null, + vt_blob, + }; + + struct JSON_value + { + JSON_value(value_type_e type_code) : + type_code(type_code) + { + } + virtual ~JSON_value() = default; + virtual void write(Pipeline*, size_t depth) const = 0; + const value_type_e type_code{vt_none}; + }; + struct JSON_dictionary: public JSON_value + { + JSON_dictionary() : + JSON_value(vt_dictionary) + { + } + ~JSON_dictionary() override = default; + void write(Pipeline*, size_t depth) const override; + std::map members; + }; + struct JSON_array; + struct JSON_string: public JSON_value + { + JSON_string(std::string const& utf8); + ~JSON_string() override = default; + void write(Pipeline*, size_t depth) const override; + std::string utf8; + }; + struct JSON_number: public JSON_value + { + JSON_number(long long val); + JSON_number(double val); + JSON_number(std::string const& val); + ~JSON_number() override = default; + void write(Pipeline*, size_t depth) const override; + std::string encoded; + }; + struct JSON_bool: public JSON_value + { + JSON_bool(bool val); + ~JSON_bool() override = default; + void write(Pipeline*, size_t depth) const override; + bool value; + }; + struct JSON_null: public JSON_value + { + JSON_null() : + JSON_value(vt_null) + { + } + ~JSON_null() override = default; + void write(Pipeline*, size_t depth) const override; + }; + struct JSON_blob: public JSON_value + { + JSON_blob(std::function fn); + ~JSON_blob() override = default; + void write(Pipeline*, size_t depth) const override; + std::function fn; + }; + + JSON(std::unique_ptr); + + static void checkSchemaInternal( + JSON_value* this_v, + JSON_value* sch_v, + unsigned long flags, + std::list& errors, + std::string prefix); + + class Members + { + friend class JSON; + + public: + ~Members() = default; + + private: + Members(std::unique_ptr); + Members(Members const&) = delete; + + std::unique_ptr value; + // start and end are only populated for objects created by parse + qpdf_offset_t start{0}; + qpdf_offset_t end{0}; + }; + + std::shared_ptr m; +}; + +struct JSON::JSON_array: public JSON_value +{ + JSON_array() : + JSON_value(vt_array) + { + } + ~JSON_array() override = default; + void write(Pipeline*, size_t depth) const override; + std::vector elements; +}; + +#endif // JSON_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/ObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/ObjectHandle.hh new file mode 100644 index 0000000..9cf4dc6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/ObjectHandle.hh @@ -0,0 +1,155 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef OBJECTHANDLE_HH +#define OBJECTHANDLE_HH + +#include +#include +#include + +#include +#include +#include + +#include +#include + +class QPDF; +class QPDF_Dictionary; +class QPDFObject; +class QPDFObjectHandle; + +namespace qpdf +{ + class Array; + class BaseDictionary; + class Dictionary; + class Integer; + class Stream; + + enum typed : std::uint8_t { strict = 0, any_flag = 1, optional = 2, any = 3, error = 4 }; + + // Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only + // methods exposed in public API are operators to convert derived objects to QPDFObjectHandle, + // QPDFObjGen and bool. + class BaseHandle + { + friend class ::QPDF; + + public: + explicit inline operator bool() const; + inline operator QPDFObjectHandle() const; + QPDF_DLL + operator QPDFObjGen() const; + + // The rest of the header file is for qpdf internal use only. + + // Return true if both object handles refer to the same underlying object. + bool + operator==(BaseHandle const& other) const + { + return obj == other.obj; + } + + // For arrays, return the number of items in the array. + // For null-like objects, return 0. + // For all other objects, return 1. + size_t size() const; + + // Return 'true' if size() == 0. + bool + empty() const + { + return size() == 0; + } + + QPDFObjectHandle operator[](size_t n) const; + QPDFObjectHandle operator[](int n) const; + + QPDFObjectHandle& at(std::string const& key) const; + bool contains(std::string const& key) const; + size_t erase(std::string const& key); + QPDFObjectHandle& find(std::string const& key) const; + bool replace(std::string const& key, QPDFObjectHandle value); + QPDFObjectHandle const& operator[](std::string const& key) const; + + std::shared_ptr copy(bool shallow = false) const; + // Recursively remove association with any QPDF object. This method may only be called + // during final destruction. + void disconnect(bool only_direct = true); + inline QPDFObjGen id_gen() const; + inline bool indirect() const; + inline bool null() const; + inline qpdf_offset_t offset() const; + inline QPDF* qpdf() const; + inline qpdf_object_type_e raw_type_code() const; + inline qpdf_object_type_e resolved_type_code() const; + inline qpdf_object_type_e type_code() const; + std::string unparse() const; + void write_json(int json_version, JSON::Writer& p) const; + static void warn(QPDF*, QPDFExc&&); + void warn(QPDFExc&&) const; + void warn(std::string const& warning) const; + + inline std::shared_ptr const& obj_sp() const; + inline QPDFObjectHandle oh() const; + + protected: + BaseHandle() = default; + BaseHandle(std::shared_ptr const& obj) : + obj(obj) {}; + BaseHandle(std::shared_ptr&& obj) : + obj(std::move(obj)) {}; + BaseHandle(BaseHandle const&) = default; + BaseHandle& operator=(BaseHandle const&) = default; + BaseHandle(BaseHandle&&) = default; + BaseHandle& operator=(BaseHandle&&) = default; + + inline BaseHandle(QPDFObjectHandle const& oh); + inline BaseHandle(QPDFObjectHandle&& oh); + + ~BaseHandle() = default; + + template + T* as() const; + + inline void assign(qpdf_object_type_e required, BaseHandle const& other); + inline void assign(qpdf_object_type_e required, BaseHandle&& other); + + inline void nullify(); + + std::string description() const; + + inline QPDFObjectHandle const& get(std::string const& key) const; + + void no_ci_warn_if(bool condition, std::string const& warning) const; + void no_ci_stop_if(bool condition, std::string const& warning) const; + void no_ci_stop_damaged_if(bool condition, std::string const& warning) const; + std::invalid_argument invalid_error(std::string const& method) const; + std::runtime_error type_error(char const* expected_type) const; + QPDFExc type_error(char const* expected_type, std::string const& message) const; + char const* type_name() const; + + std::shared_ptr obj; + }; + +} // namespace qpdf + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/PDFVersion.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/PDFVersion.hh new file mode 100644 index 0000000..32b1df5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/PDFVersion.hh @@ -0,0 +1,65 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PDFVERSION_HH +#define PDFVERSION_HH + +#include +#include + +// Represent a PDF version. PDF versions are typically major.minor, but PDF 1.7 has several +// extension levels as the ISO 32000 spec was in progress. This class helps with comparison of +// versions. +class PDFVersion +{ + public: + PDFVersion() = default; + PDFVersion(PDFVersion const&) = default; + PDFVersion& operator=(PDFVersion const&) = default; + + QPDF_DLL + PDFVersion(int major, int minor, int extension = 0); + QPDF_DLL + bool operator<(PDFVersion const& rhs) const; + QPDF_DLL + bool operator==(PDFVersion const& rhs) const; + + // Replace this version with the other one if the other one is greater. + QPDF_DLL + void updateIfGreater(PDFVersion const& other); + + // Initialize a string and integer suitable for passing to QPDFWriter::setMinimumPDFVersion or + // QPDFWriter::forcePDFVersion. + QPDF_DLL + void getVersion(std::string& version, int& extension_level) const; + + QPDF_DLL + int getMajor() const; + QPDF_DLL + int getMinor() const; + QPDF_DLL + int getExtensionLevel() const; + + private: + int major_version{0}; + int minor_version{0}; + int extension_level{0}; +}; + +#endif // PDFVERSION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pipeline.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pipeline.hh new file mode 100644 index 0000000..6e07c4f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pipeline.hh @@ -0,0 +1,115 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PIPELINE_HH +#define PIPELINE_HH + +#include + +#include +#include + +// Generalized Pipeline interface. By convention, subclasses of Pipeline are called Pl_Something. +// +// When an instance of Pipeline is created with a pointer to a next pipeline, that pipeline writes +// its data to the next one when it finishes with it. In order to make possible a usage style in +// which a pipeline may be passed to a function which may stick other pipelines in front of it, the +// allocator of a pipeline is responsible for its destruction. In other words, one pipeline object +// does not attempt to manage the memory of its successor. +// +// The client is required to call finish() before destroying a Pipeline in order to avoid loss of +// data. A Pipeline class should not throw an exception in the destructor if this hasn't been done +// though since doing so causes too much trouble when deleting pipelines during error conditions. +// +// Some pipelines are reusable (i.e., you can call write() after calling finish() and can call +// finish() multiple times) while others are not. It is up to the caller to use a pipeline +// according to its own restrictions. +// +// Remember to use QPDF_DLL_CLASS on anything derived from Pipeline so it will work with +// dynamic_cast across the shared object boundary. +class QPDF_DLL_CLASS Pipeline +{ + public: + QPDF_DLL + Pipeline(char const* identifier, Pipeline* next); + + virtual ~Pipeline() = default; + + // Subclasses should implement write and finish to do their jobs and then, if they are not + // end-of-line pipelines, call getNext()->write or getNext()->finish. + QPDF_DLL + virtual void write(unsigned char const* data, size_t len) = 0; + QPDF_DLL + virtual void finish() = 0; + QPDF_DLL + std::string getIdentifier() const; + + // These are convenience methods for making it easier to write certain other types of data to + // pipelines without having to cast. The methods that take char const* expect null-terminated C + // strings and do not write the null terminators. + QPDF_DLL + void writeCStr(char const* cstr); + QPDF_DLL + void writeString(std::string const&); + // This allows *p << "x" << "y" but is not intended to be a general purpose << compatible with + // ostream and does not have local awareness or the ability to be "imbued" with properties. + QPDF_DLL + Pipeline& operator<<(char const* cstr); + QPDF_DLL + Pipeline& operator<<(std::string const&); + QPDF_DLL + Pipeline& operator<<(short); + QPDF_DLL + Pipeline& operator<<(int); + QPDF_DLL + Pipeline& operator<<(long); + QPDF_DLL + Pipeline& operator<<(long long); + QPDF_DLL + Pipeline& operator<<(unsigned short); + QPDF_DLL + Pipeline& operator<<(unsigned int); + QPDF_DLL + Pipeline& operator<<(unsigned long); + QPDF_DLL + Pipeline& operator<<(unsigned long long); + + // Overloaded write to reduce casting + QPDF_DLL + void write(char const* data, size_t len); + + protected: + QPDF_DLL + Pipeline* getNext(bool allow_null = false); + + Pipeline* + next() const noexcept + { + return next_; + } + std::string identifier; + + private: + Pipeline(Pipeline const&) = delete; + Pipeline& operator=(Pipeline const&) = delete; + + Pipeline* next_; +}; + +#endif // PIPELINE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Buffer.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Buffer.hh new file mode 100644 index 0000000..b3b7ed6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Buffer.hh @@ -0,0 +1,76 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_BUFFER_HH +#define PL_BUFFER_HH + +#include +#include + +#include +#include + +// This pipeline accumulates the data passed to it into a memory buffer. Each subsequent use of +// this buffer appends to the data accumulated so far. getBuffer() may be called only after calling +// finish() and before calling any subsequent write(). At that point, a dynamically allocated +// Buffer object is returned and the internal buffer is reset. The caller is responsible for +// deleting the returned Buffer. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it. +class QPDF_DLL_CLASS Pl_Buffer: public Pipeline +{ + public: + QPDF_DLL + Pl_Buffer(char const* identifier, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_Buffer() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + + // Each call to getBuffer() resets this object -- see notes above. + // The caller is responsible for deleting the returned Buffer object. See also + // getBufferSharedPointer() and getMallocBuffer(). + QPDF_DLL + Buffer* getBuffer(); + + // Same as getBuffer but wraps the result in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // getMallocBuffer behaves in the same was as getBuffer except the buffer is allocated with + // malloc(), making it suitable for use when calling from other languages. If there is no data, + // *buf is set to a null pointer and *len is set to 0. Otherwise, *buf is a buffer of size *len + // allocated with malloc(). It is the caller's responsibility to call free() on the buffer. + QPDF_DLL + void getMallocBuffer(unsigned char** buf, size_t* len); + + // Same as getBuffer but returns the result as a string. + QPDF_DLL + std::string getString(); + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_BUFFER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Concatenate.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Concatenate.hh new file mode 100644 index 0000000..48a7ca8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Concatenate.hh @@ -0,0 +1,64 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_CONCATENATE_HH +#define PL_CONCATENATE_HH + +#include + +// This pipeline will drop all regular finish calls rather than passing them onto next. To finish +// downstream streams, call manualFinish. This makes it possible to pipe multiple streams (e.g. +// with QPDFObjectHandle::pipeStreamData) to a downstream like Pl_Flate that can't handle multiple +// calls to finish(). +class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline +{ + public: + QPDF_DLL + Pl_Concatenate(char const* identifier, Pipeline* next); + + QPDF_DLL + ~Pl_Concatenate() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + + QPDF_DLL + void finish() override; + + // At the very end, call manualFinish to actually finish the rest of the pipeline. + QPDF_DLL + void manualFinish(); + + private: + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Concatenate; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::unique_ptr m{nullptr}; +}; + +#endif // PL_CONCATENATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Count.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Count.hh new file mode 100644 index 0000000..2189b81 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Count.hh @@ -0,0 +1,52 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_COUNT_HH +#define PL_COUNT_HH + +#include +#include + +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Count: public Pipeline +{ + public: + QPDF_DLL + Pl_Count(char const* identifier, Pipeline* next); + QPDF_DLL + ~Pl_Count() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; + // Returns the number of bytes written + QPDF_DLL + qpdf_offset_t getCount() const; + // Returns the last character written, or '\0' if no characters have been written (in which case + // getCount() returns 0) + QPDF_DLL + unsigned char getLastChar() const; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_COUNT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_DCT.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_DCT.hh new file mode 100644 index 0000000..48f2594 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_DCT.hh @@ -0,0 +1,101 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DCT_HH +#define PL_DCT_HH + +#include + +#include +#include + +// jpeglib.h must be included after cstddef or else it messes up the definition of size_t. +#include + +class QPDF_DLL_CLASS Pl_DCT: public Pipeline +{ + public: + // Constructor for decompressing image data + QPDF_DLL + Pl_DCT(char const* identifier, Pipeline* next); + + // Limit the memory used by jpeglib when decompressing data. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setMemoryLimit(long limit); + + // Limit the number of scans used by jpeglib when decompressing progressive jpegs. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setScanLimit(int limit); + + // Treat corrupt data as a runtime error rather than attempting to decompress regardless. This + // is the qpdf default behaviour. To attempt to decompress corrupt data set 'treat_as_error' to + // false. + // NB This is a static option affecting all Pl_DCT instances. + QPDF_DLL + static void setThrowOnCorruptData(bool treat_as_error); + + class QPDF_DLL_CLASS CompressConfig + { + public: + QPDF_DLL + CompressConfig() = default; + QPDF_DLL + virtual ~CompressConfig() = default; + virtual void apply(jpeg_compress_struct*) = 0; + }; + + QPDF_DLL + static std::unique_ptr + make_compress_config(std::function); + + // Constructor for compressing image data + QPDF_DLL + Pl_DCT( + char const* identifier, + Pipeline* next, + JDIMENSION image_width, + JDIMENSION image_height, + int components, + J_COLOR_SPACE color_space, + CompressConfig* config_callback = nullptr); + + QPDF_DLL + ~Pl_DCT() override; + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void compress(void* cinfo); + QPDF_DLL_PRIVATE + void decompress(void* cinfo); + + enum action_e { a_compress, a_decompress }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_DCT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Discard.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Discard.hh new file mode 100644 index 0000000..b0073cd --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Discard.hh @@ -0,0 +1,41 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_DISCARD_HH +#define PL_DISCARD_HH + +#include + +// This pipeline discards its output. It is an end-of-line pipeline (with no next). +// +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). +class QPDF_DLL_CLASS Pl_Discard: public Pipeline +{ + public: + QPDF_DLL + Pl_Discard(); + QPDF_DLL + ~Pl_Discard() override; + QPDF_DLL + void write(unsigned char const*, size_t) override; + QPDF_DLL + void finish() override; +}; + +#endif // PL_DISCARD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Flate.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Flate.hh new file mode 100644 index 0000000..2347a91 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Flate.hh @@ -0,0 +1,126 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef PL_FLATE_HH +#define PL_FLATE_HH + +#include +#include +#include +#include +#include + +class QPDF_DLL_CLASS Pl_Flate: public Pipeline +{ + public: + static unsigned int const def_bufsize = 65536; + + enum action_e { a_inflate, a_deflate }; + + QPDF_DLL + Pl_Flate( + char const* identifier, + Pipeline* next, + action_e action, + unsigned int out_bufsize = def_bufsize); + QPDF_DLL + ~Pl_Flate() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_Flate instances. + QPDF_DLL + static unsigned long long memory_limit(); + QPDF_DLL + static void memory_limit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + // Globally set compression level from 1 (fastest, least + // compression) to 9 (slowest, most compression). Use -1 to set + // the default compression level. This is passed directly to zlib. + // This method returns a pointer to the current Pl_Flate object so + // you can create a pipeline with + // Pl_Flate(...)->setCompressionLevel(...) + QPDF_DLL + static void setCompressionLevel(int); + + QPDF_DLL + void setWarnCallback(std::function callback); + + // Returns true if qpdf was built with zopfli support. + QPDF_DLL + static bool zopfli_supported(); + + // Returns true if zopfli is enabled. Zopfli is enabled if QPDF_ZOPFLI is set to a value other + // than "disabled" and zopfli support is compiled in. + QPDF_DLL + static bool zopfli_enabled(); + + // If zopfli is supported, returns true. Otherwise, check the QPDF_ZOPFLI + // environment variable as follows: + // - "disabled" or "silent": return true + // - "force": qpdf_exit_error, throw an exception + // - Any other value: issue a warning, and return false + QPDF_DLL + static bool zopfli_check_env(QPDFLogger* logger = nullptr); + + private: + QPDF_DLL_PRIVATE + void handleData(unsigned char const* data, size_t len, int flush); + QPDF_DLL_PRIVATE + void checkError(char const* prefix, int error_code); + QPDF_DLL_PRIVATE + void warn(char const*, int error_code); + QPDF_DLL_PRIVATE + void finish_zopfli(); + + QPDF_DLL_PRIVATE + static int compression_level; + + class QPDF_DLL_PRIVATE Members + { + friend class Pl_Flate; + + public: + Members(size_t out_bufsize, action_e action); + ~Members(); + + private: + Members(Members const&) = delete; + + std::shared_ptr outbuf; + size_t out_bufsize; + action_e action; + bool initialized; + void* zdata; + unsigned long long written{0}; + std::function callback; + std::unique_ptr zopfli_buf; + }; + + std::unique_ptr m; +}; + +#endif // PL_FLATE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Function.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Function.hh new file mode 100644 index 0000000..081a4e1 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_Function.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_FUNCTION_HH +#define PL_FUNCTION_HH + +#include + +#include + +// This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can +// be reused. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". +// +// It is okay to keep calling write() after a previous write throws an exception as long as the +// delegated function allows it. +class QPDF_DLL_CLASS Pl_Function: public Pipeline +{ + public: + typedef std::function writer_t; + + // The supplied function is called every time write is called. + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_t fn); + + // The supplied C-style function is called every time write is called. The udata option is + // passed into the function with each call. If the function returns a non-zero value, a runtime + // error is thrown. + typedef int (*writer_c_t)(unsigned char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata); + typedef int (*writer_c_char_t)(char const*, size_t, void*); + QPDF_DLL + Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata); + + QPDF_DLL + ~Pl_Function() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_FUNCTION_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_OStream.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_OStream.hh new file mode 100644 index 0000000..0f912f7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_OStream.hh @@ -0,0 +1,50 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_OSTREAM_HH +#define PL_OSTREAM_HH + +#include + +#include + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. +// +// This pipeline is reusable. +class QPDF_DLL_CLASS Pl_OStream: public Pipeline +{ + public: + // os is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_OStream(char const* identifier, std::ostream& os); + QPDF_DLL + ~Pl_OStream() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_OSTREAM_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_QPDFTokenizer.hh new file mode 100644 index 0000000..e26b856 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_QPDFTokenizer.hh @@ -0,0 +1,59 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_QPDFTOKENIZER_HH +#define PL_QPDFTOKENIZER_HH + +#include + +#include +#include +#include + +#include + +// Tokenize the incoming text using QPDFTokenizer and pass the tokens in turn to a +// QPDFObjectHandle::TokenFilter object. All bytes of incoming content will be included in exactly +// one token and passed downstream. +// +// This is a very low-level interface for working with token filters. Most code will want to use +// QPDFObjectHandle::filterPageContents or QPDFObjectHandle::addTokenFilter. See QPDFObjectHandle.hh +// for details. +class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline +{ + public: + // Whatever pipeline is provided as "next" will be set as the pipeline that the token filter + // writes to. If next is not provided, any output written by the filter will be discarded. + QPDF_DLL + Pl_QPDFTokenizer( + char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + QPDF_DLL + ~Pl_QPDFTokenizer() override; + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_RunLength.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_RunLength.hh new file mode 100644 index 0000000..4fc91fa --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_RunLength.hh @@ -0,0 +1,60 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_RUNLENGTH_HH +#define PL_RUNLENGTH_HH + +#include + +class QPDF_DLL_CLASS Pl_RunLength: public Pipeline +{ + public: + enum action_e { a_encode, a_decode }; + + QPDF_DLL + Pl_RunLength(char const* identifier, Pipeline* next, action_e action); + QPDF_DLL + ~Pl_RunLength() override; + + // Limit the memory used. + // NB This is a static option affecting all Pl_RunLength instances. + QPDF_DLL + static void setMemoryLimit(unsigned long long limit); + + QPDF_DLL + void write(unsigned char const* data, size_t len) override; + QPDF_DLL + void finish() override; + + private: + QPDF_DLL_PRIVATE + void encode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void decode(unsigned char const* data, size_t len); + QPDF_DLL_PRIVATE + void flush_encode(); + + enum state_e { st_top, st_copying, st_run }; + + class Members; + + std::unique_ptr m; +}; + +#endif // PL_RUNLENGTH_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_StdioFile.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_StdioFile.hh new file mode 100644 index 0000000..4c70528 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_StdioFile.hh @@ -0,0 +1,51 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +// End-of-line pipeline that simply writes its data to a stdio FILE* object. + +#ifndef PL_STDIOFILE_HH +#define PL_STDIOFILE_HH + +#include + +#include + +// +// This pipeline is reusable. +// +class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline +{ + public: + // f is externally maintained; this class just writes to and flushes it. It does not close it. + QPDF_DLL + Pl_StdioFile(char const* identifier, FILE* f); + QPDF_DLL + ~Pl_StdioFile() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + std::unique_ptr m; +}; + +#endif // PL_STDIOFILE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_String.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_String.hh new file mode 100644 index 0000000..a907b44 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Pl_String.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef PL_STRING_HH +#define PL_STRING_HH + +#include + +#include + +// This pipeline accumulates the data passed to it into a std::string, a reference to which is +// passed in at construction. Each subsequent use of this pipeline appends to the data accumulated +// so far. +// +// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also +// pass the data through to it and will forward finish() to it. +// +// It is okay to not call finish() on this pipeline if it has no "next". This makes it easy to stick +// this in front of another pipeline to capture data that is written to the other pipeline without +// interfering with when finish is called on the other pipeline and without having to put a +// Pl_Concatenate after it. +class QPDF_DLL_CLASS Pl_String: public Pipeline +{ + public: + QPDF_DLL + Pl_String(char const* identifier, Pipeline* next, std::string& s); + QPDF_DLL + ~Pl_String() override; + + QPDF_DLL + void write(unsigned char const* buf, size_t len) override; + QPDF_DLL + void finish() override; + + private: + class Members; + + std::unique_ptr m; +}; + +#endif // PL_STRING_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/PointerHolder.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/PointerHolder.hh new file mode 100644 index 0000000..2df2d25 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/PointerHolder.hh @@ -0,0 +1,245 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef POINTERHOLDER_HH +#define POINTERHOLDER_HH + +#define POINTERHOLDER_IS_SHARED_POINTER + +#ifndef POINTERHOLDER_TRANSITION +// 0 = no deprecation warnings, backward-compatible API +// 1 = make PointerHolder(T*) explicit +// 2 = warn for use of getPointer() and getRefcount() +// 3 = warn for all use of PointerHolder +// 4 = don't define PointerHolder at all +# define POINTERHOLDER_TRANSITION 4 +#endif // !defined(POINTERHOLDER_TRANSITION) + +#if POINTERHOLDER_TRANSITION < 4 + +// *** WHAT IS HAPPENING *** + +// In qpdf 11, PointerHolder was replaced with std::shared_ptr +// wherever it appeared in the qpdf API. The PointerHolder object is +// now derived from std::shared_ptr to provide a backward-compatible +// interface and is mutually assignable with std::shared_ptr. Code +// that uses containers of PointerHolder will require adjustment. + +// In qpdf 11, a backward-compatible PointerHolder was provided with a +// warning if POINTERHOLDER_TRANSITION was not defined. Starting in +// qpdf 12, PointerHolder is absent if POINTERHOLDER_TRANSITION is not +// defined. In a future version of qpdf, PointerHolder will be removed +// outright if it becomes inconvenient to keep it around. + +// *** HOW TO TRANSITION *** + +// The symbol POINTERHOLDER_TRANSITION can be defined to help you +// transition your code away from PointerHolder. You can define it +// before including any qpdf header files or including its definition +// in your build configuration. If not defined, it automatically gets +// defined to 4, which excludes PointerHolder entirely. + +// If you want to work gradually to transition your code away from +// PointerHolder, you can define POINTERHOLDER_TRANSITION and fix the +// code so it compiles without warnings and works correctly. If you +// want to be able to continue to support old qpdf versions at the +// same time, you can write code like this: + +// #ifndef POINTERHOLDER_IS_SHARED_POINTER +// ... use PointerHolder as before 10.6 +// #else +// ... use PointerHolder or shared_ptr as needed +// #endif + +// Each level of POINTERHOLDER_TRANSITION exposes differences between +// PointerHolder and std::shared_ptr. The easiest way to transition is +// to increase POINTERHOLDER_TRANSITION in steps of 1 so that you can +// test and handle changes incrementally. + +// POINTERHOLDER_TRANSITION = 1 +// +// PointerHolder has an implicit constructor that takes a T*, so +// you can replace a PointerHolder's pointer by directly assigning +// a T* to it or pass a T* to a function that expects a +// PointerHolder. std::shared_ptr does not have this (risky) +// behavior. When POINTERHOLDER_TRANSITION = 1, PointerHolder's T* +// constructor is declared explicit. For compatibility with +// std::shared_ptr, you can still assign nullptr to a PointerHolder. +// Constructing all your PointerHolder instances explicitly is +// backward compatible, so you can make this change without +// conditional compilation and still use the changes with older qpdf +// versions. +// +// Also defined is a make_pointer_holder method that acts like +// std::make_shared. You can use this as well, but it is not +// compatible with qpdf prior to 10.6 and not necessary with qpdf +// newer than 10.6.3. Like std::make_shared, make_pointer_holder +// can only be used when the constructor implied by its arguments is +// public. If you previously used this, you can replace it width +// std::make_shared now. + +// POINTERHOLDER_TRANSITION = 2 +// +// std::shared_ptr has get() and use_count(). PointerHolder has +// getPointer() and getRefcount(). In 10.6.0, get() and use_count() +// were added as well. When POINTERHOLDER_TRANSITION = 2, getPointer() +// and getRefcount() are deprecated. Fix deprecation warnings by +// replacing with get() and use_count(). This breaks compatibility +// with qpdf older than 10.6. Search for CONST BEHAVIOR for an +// additional note. +// +// Once your code is clean at POINTERHOLDER_TRANSITION = 2, the only +// remaining issues that prevent simple replacement of PointerHolder +// with std::shared_ptr are shared arrays and containers, and neither +// of these are used in the qpdf API. + +// POINTERHOLDER_TRANSITION = 3 +// +// Warn for all use of PointerHolder. This helps you remove all use +// of PointerHolder from your code and use std::shared_ptr instead. +// You will also have to transition any containers of PointerHolder in +// your code. + +// POINTERHOLDER_TRANSITION = 4 +// +// Suppress definition of the PointerHolder type entirely. This is +// the default behavior starting with qpdf 12. + +// CONST BEHAVIOR + +// PointerHolder has had a long-standing bug in its const behavior. +// const PointerHolder's getPointer() method returns a T const*. +// This is incorrect and is not how regular pointers or standard +// library smart pointers behave. Making a PointerHolder const +// should prevent reassignment of its pointer but not affect the thing +// it points to. For that, use PointerHolder. The new get() +// method behaves correctly in this respect and is therefore slightly +// different from getPointer(). This shouldn't break any correctly +// written code. If you are relying on the incorrect behavior, use +// PointerHolder instead. + +# include +# include + +template +class PointerHolder: public std::shared_ptr +{ + public: +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(std::shared_ptr other) : + std::shared_ptr(other) + { + } +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# if POINTERHOLDER_TRANSITION >= 1 + explicit +# endif // POINTERHOLDER_TRANSITION >= 1 +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(T* pointer = 0) : + std::shared_ptr(pointer) + { + } + // Create a shared pointer to an array +# if POINTERHOLDER_TRANSITION >= 3 + [[deprecated("use std::shared_ptr instead")]] +# endif // POINTERHOLDER_TRANSITION >= 3 + PointerHolder(bool, T* pointer) : + std::shared_ptr(pointer, std::default_delete()) + { + } + + virtual ~PointerHolder() = default; + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T* + getPointer() + { + return this->get(); + } +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + T const* + getPointer() const + { + return this->get(); + } + +# if POINTERHOLDER_TRANSITION >= 2 + [[deprecated("use PointerHolder::get() instead of getPointer()")]] +# endif // POINTERHOLDER_TRANSITION >= 2 + int + getRefcount() const + { + return static_cast(this->use_count()); + } + + PointerHolder& + operator=(decltype(nullptr)) + { + std::shared_ptr::operator=(nullptr); + return *this; + } + T const& + operator*() const + { + return *(this->get()); + } + T& + operator*() + { + return *(this->get()); + } + + T const* + operator->() const + { + return this->get(); + } + T* + operator->() + { + return this->get(); + } +}; + +template +inline PointerHolder +make_pointer_holder(_Args&&... __args) +{ + return PointerHolder(new T(__args...)); +} + +template +PointerHolder +make_array_pointer_holder(size_t n) +{ + return PointerHolder(true, new T[n]); +} + +#endif // POINTERHOLDER_TRANSITION < 4 +#endif // POINTERHOLDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QIntC.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QIntC.hh new file mode 100644 index 0000000..cef8aca --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QIntC.hh @@ -0,0 +1,310 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QINTC_HH +#define QINTC_HH + +#include +#include +#include +#include +#include +#include +#include +#include + +// This namespace provides safe integer conversion that detects +// overflows. It uses short, cryptic names for brevity. + +namespace QIntC // QIntC = qpdf Integer Conversion +{ + // to_u is here for backward-compatibility from before we required + // C++-11. + template + class to_u + { + public: + typedef typename std::make_unsigned::type type; + }; + + // Basic IntConverter class, which converts an integer from the + // From class to one of the To class if it can be done safely and + // throws a range_error otherwise. This class is specialized for + // each permutation of signed/unsigned for the From and To + // classes. + template < + typename From, + typename To, + bool From_signed = std::numeric_limits::is_signed, + bool To_signed = std::numeric_limits::is_signed> + class IntConverter + { + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both unsigned. + if (i > std::numeric_limits::max()) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From and To are both signed. + if ((i < std::numeric_limits::min()) || (i > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is signed, and To is unsigned. If i > 0, it's safe to + // convert it to the corresponding unsigned type and to + // compare with To's max. + auto ii = static_cast::type>(i); + if ((i < 0) || (ii > std::numeric_limits::max())) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte signed type to a " << sizeof(To) << "-byte unsigned type"; + throw std::range_error(msg.str()); + } + }; + + template + class IntConverter + { + public: + inline static To + convert(From const& i) + { + // From is unsigned, and to is signed. Convert To's max to the + // unsigned version of To and compare i against that. + auto maxval = static_cast::type>(std::numeric_limits::max()); + if (i > maxval) { + error(i); + } + return static_cast(i); + } + + static void + error(From i) + { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "integer out of range converting " << i << " from a " << sizeof(From) + << "-byte unsigned type to a " << sizeof(To) << "-byte signed type"; + throw std::range_error(msg.str()); + } + }; + + // Specific converters. The return type of each function must match + // the second template parameter to IntConverter. + template + inline char + to_char(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned char + to_uchar(T const& i) + { + return IntConverter::convert(i); + } + + template + inline short + to_short(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned short + to_ushort(T const& i) + { + return IntConverter::convert(i); + } + + template + inline int + to_int(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned int + to_uint(T const& i) + { + return IntConverter::convert(i); + } + + template + inline size_t + to_size(T const& i) + { + return IntConverter::convert(i); + } + + template + inline qpdf_offset_t + to_offset(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long + to_long(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long + to_ulong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline long long + to_longlong(T const& i) + { + return IntConverter::convert(i); + } + + template + inline unsigned long long + to_ulonglong(T const& i) + { + return IntConverter::convert(i); + } + + template + void + range_check_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::max() - cur) < delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::min() - cur) > delta)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "adding " << delta << " to " << cur << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check(T const& cur, T const& delta) + { + if ((delta > 0) != (cur > 0)) { + return; + } + QIntC::range_check_error(cur, delta); + } + + template + void + range_check_subtract_error(T const& cur, T const& delta) + { + if ((delta > 0) && ((std::numeric_limits::min() + delta) > cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur + << " would cause an integer underflow"; + throw std::range_error(msg.str()); + } else if ((delta < 0) && ((std::numeric_limits::max() + delta) < cur)) { + std::ostringstream msg; + msg.imbue(std::locale::classic()); + msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow"; + throw std::range_error(msg.str()); + } + } + + template + inline void + range_check_subtract(T const& cur, T const& delta) + { + if ((delta >= 0) == (cur >= 0)) { + return; + } + QIntC::range_check_subtract_error(cur, delta); + } +}; // namespace QIntC + +#endif // QINTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDF.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDF.hh new file mode 100644 index 0000000..5f990b7 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDF.hh @@ -0,0 +1,804 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDF_HH +#define QPDF_HH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFLogger; + +class QPDF +{ + public: + // Get the current version of the QPDF software. See also qpdf/DLL.h + QPDF_DLL + static std::string const& QPDFVersion(); + + QPDF_DLL + QPDF(); + QPDF_DLL + ~QPDF(); + + QPDF_DLL + static std::shared_ptr create(); + + // Associate a file with a QPDF object and do initial parsing of the file. PDF objects are not + // read until they are needed. A QPDF object may be associated with only one file in its + // lifetime. This method must be called before any methods that potentially ask for information + // about the PDF file are called. Prior to calling this, the only methods that are allowed are + // those that set parameters. If the input file is not encrypted, either a null password or an + // empty password can be used. If the file is encrypted, either the user password or the owner + // password may be supplied. The method setPasswordIsHexKey may be called prior to calling this + // method or any of the other process methods to force the password to be interpreted as a raw + // encryption key. See comments on setPasswordIsHexKey for more information. + QPDF_DLL + void processFile(char const* filename, char const* password = nullptr); + + // Parse a PDF from a stdio FILE*. The FILE must be open in binary mode and must be seekable. + // It may be open read only. This works exactly like processFile except that the PDF file is + // read from an already opened FILE*. If close_file is true, the file will be closed at the + // end. Otherwise, the caller is responsible for closing the file. + QPDF_DLL + void processFile( + char const* description, FILE* file, bool close_file, char const* password = nullptr); + + // Parse a PDF file loaded into a memory buffer. This works exactly like processFile except + // that the PDF file is in memory instead of on disk. The description appears in any warning or + // error message in place of the file name. The buffer is owned by the caller and must remain + // valid for the lifetime of the QPDF object. + QPDF_DLL + void processMemoryFile( + char const* description, char const* buf, size_t length, char const* password = nullptr); + + // Parse a PDF file loaded from a custom InputSource. If you have your own method of retrieving + // a PDF file, you can subclass InputSource and use this method. + QPDF_DLL + void processInputSource(std::shared_ptr, char const* password = nullptr); + + // Create a PDF from an input source that contains JSON as written by writeJSON (or qpdf + // --json-output, version 2 or higher). The JSON must be a complete representation of a PDF. See + // "qpdf JSON" in the manual for details. The input JSON may be arbitrarily large. QPDF does not + // load stream data into memory for more than one stream at a time, even if the stream data is + // specified inline. + QPDF_DLL + void createFromJSON(std::string const& json_file); + QPDF_DLL + void createFromJSON(std::shared_ptr); + + // Update a PDF from an input source that contains JSON in the same format as is written by + // writeJSON (or qpdf --json-output, version 2 or higher). Objects in the PDF and not in the + // JSON are not modified. See "qpdf JSON" in the manual for details. As with createFromJSON, the + // input JSON may be arbitrarily large. + QPDF_DLL + void updateFromJSON(std::string const& json_file); + QPDF_DLL + void updateFromJSON(std::shared_ptr); + + // Write qpdf JSON format to the pipeline "p". The only supported version is 2. The finish() + // method is not called on the pipeline. + // + // The decode_level parameter controls which streams are uncompressed in the JSON. Use + // qpdf_dl_none to preserve all stream data exactly as it appears in the input. The possible + // values for json_stream_data can be found in qpdf/Constants.h and correspond to the + // --json-stream-data command-line argument. If json_stream_data is qpdf_sj_file, file_prefix + // must be specified. Each stream will be written to a file whose path is constructed by + // appending "-nnn" to file_prefix, where "nnn" is the object number (not zero-filled). If + // wanted_objects is empty, write all objects. Otherwise, write only objects whose keys are in + // wanted_objects. Keys may be either "trailer" or of the form "obj:n n R". Invalid keys are + // ignored. This corresponds to the --json-object command-line argument. + // + // QPDF is efficient with regard to memory when writing, allowing you to write arbitrarily large + // PDF files to a pipeline. You can use a pipeline like Pl_Buffer or Pl_String to capture the + // JSON output in memory, but do so with caution as this will allocate enough memory to hold the + // entire PDF file. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // This version of writeJSON enables writing only the "qpdf" key of an in-progress dictionary. + // If the value of "complete" is true, a complete JSON object containing only the "qpdf" key is + // written to the pipeline. If the value of "complete" is false, the "qpdf" key and its value + // are written to the pipeline assuming that a dictionary is already open. The parameter + // first_key indicates whether this is the first key in an in-progress dictionary. It will be + // set to false by writeJSON. The "qpdf" key and value are written as if at depth 1 in a + // prettified JSON output. Remaining arguments are the same as the above version. + QPDF_DLL + void writeJSON( + int version, + Pipeline* p, + bool complete, + bool& first_key, + qpdf_stream_decode_level_e decode_level, + qpdf_json_stream_data_e json_stream_data, + std::string const& file_prefix, + std::set wanted_objects); + + // Close or otherwise release the input source. Once this has been called, no other methods of + // qpdf can be called safely except for getWarnings and anyWarnings(). After this has been + // called, it is safe to perform operations on the input file such as deleting or renaming it. + QPDF_DLL + void closeInputSource(); + + // For certain forensic or investigatory purposes, it may sometimes be useful to specify the + // encryption key directly, even though regular PDF applications do not provide a way to do + // this. Calling setPasswordIsHexKey(true) before calling any of the process methods will bypass + // the normal encryption key computation or recovery mechanisms and interpret the bytes in the + // password as a hex-encoded encryption key. Note that we hex-encode the key because it may + // contain null bytes and therefore can't be represented in a char const*. + QPDF_DLL + void setPasswordIsHexKey(bool); + + // Create a QPDF object for an empty PDF. This PDF has no pages or objects other than a minimal + // trailer, a document catalog, and a /Pages tree containing zero pages. Pages and other + // objects can be added to the file in the normal way, and the trailer and document catalog can + // be mutated. Calling this method is equivalent to calling processFile on an equivalent PDF + // file. See the pdf-create.cc example for a demonstration of how to use this method to create + // a PDF file from scratch. + QPDF_DLL + void emptyPDF(); + + // From 10.1: register a new filter implementation for a specific stream filter. You can add + // your own implementations for new filter types or override existing ones provided by the + // library. Registered stream filters are used for decoding only as you can override encoding + // with stream data providers. For example, you could use this method to add support for one of + // the other filter types by using additional third-party libraries that qpdf does not presently + // use. The standard filters are implemented using QPDFStreamFilter classes. + QPDF_DLL + static void registerStreamFilter( + std::string const& filter_name, std::function()> factory); + + // Parameter settings + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // Note that no normal QPDF operations generate output to standard output, so for applications + // that just wish to avoid creating output for warnings and don't call any check functions, + // calling setSuppressWarnings(true) is sufficient. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // If true, ignore any cross-reference streams in a hybrid file (one that contains both + // cross-reference streams and cross-reference tables). This can be useful for testing to + // ensure that a hybrid file would work with an older reader. + QPDF_DLL + void setIgnoreXRefStreams(bool); + + // By default, any warnings are issued to std::cerr or the error stream specified in a call to + // setOutputStreams as they are encountered. If this method is called with a true value, + // reporting of warnings is suppressed. You may still retrieve warnings by calling getWarnings. + QPDF_DLL + void setSuppressWarnings(bool); + + // Set the maximum number of warnings. A QPDFExc is thrown if the limit is exceeded. + QPDF_DLL + void setMaxWarnings(size_t); + + // By default, QPDF will try to recover if it finds certain types of errors in PDF files. If + // turned off, it will throw an exception on the first such problem it finds without attempting + // recovery. + QPDF_DLL + void setAttemptRecovery(bool); + + // Tell other QPDF objects that streams copied from this QPDF need to be fully copied when + // copyForeignObject is called on them. Calling setIgnoreXRefStreams(true) on a QPDF object + // makes it possible for the object and its input source to disappear before streams copied from + // it are written with the destination QPDF object. Confused? Ordinarily, if you are going to + // copy objects from a source QPDF object to a destination QPDF object using copyForeignObject + // or addPage, the source object's input source must stick around until after the destination + // PDF is written. If you call this method on the source QPDF object, it sends a signal to the + // destination object that it must fully copy the stream data when copyForeignObject. It will do + // this by making a copy in RAM. Ordinarily the stream data is copied lazily to avoid + // unnecessary duplication of the stream data. Note that the stream data is copied into RAM only + // once regardless of how many objects the stream is copied into. The result is that, if you + // called setImmediateCopyFrom(true) on a given QPDF object prior to copying any of its streams, + // you do not need to keep it or its input source around after copying its objects to another + // QPDF. This is true even if the source streams use StreamDataProvider. Note that this method + // is called on the QPDF object you are copying FROM, not the one you are copying to. The + // reasoning for this is that there's no reason a given QPDF may not get objects copied to it + // from a variety of other objects, some transient and some not. Since what's relevant is + // whether the source QPDF is transient, the method must be called on the source QPDF, not the + // destination one. This method will make a copy of the stream in RAM, so be sure you have + // enough memory to simultaneously hold all the streams you're copying. + QPDF_DLL + void setImmediateCopyFrom(bool); + + // Other public methods + + // Return the list of warnings that have been issued so far and clear the list. This method may + // be called even if processFile throws an exception. Note that if setSuppressWarnings was not + // called or was called with a false value, any warnings retrieved here will have already been + // output. + QPDF_DLL + std::vector getWarnings(); + + // Indicate whether any warnings have been issued so far. Does not clear the list of warnings. + QPDF_DLL + bool anyWarnings() const; + + // Indicate the number of warnings that have been issued since the last call to getWarnings. + // Does not clear the list of warnings. + QPDF_DLL + size_t numWarnings() const; + + // Return an application-scoped unique ID for this QPDF object. This is not a globally unique + // ID. It is constructed using a timestamp and a random number and is intended to be unique + // among QPDF objects that are created by a single run of an application. While it's very likely + // that these are actually globally unique, it is not recommended to use them for long-term + // purposes. + QPDF_DLL + unsigned long long getUniqueId() const; + + // Issue a warning on behalf of this QPDF object. It will be emitted with other warnings, + // following warning suppression rules, and it will be available with getWarnings(). + QPDF_DLL + void warn(QPDFExc const& e); + // Same as above but creates the QPDFExc object using the arguments passed to warn. The filename + // argument to QPDFExc is omitted. This method uses the filename associated with the QPDF + // object. + QPDF_DLL + void warn( + qpdf_error_code_e error_code, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // Return the filename associated with the QPDF object. + QPDF_DLL + std::string getFilename() const; + // Return PDF Version and extension level together as a PDFVersion object + QPDF_DLL + PDFVersion getVersionAsPDFVersion(); + // Return just the PDF version from the file + QPDF_DLL + std::string getPDFVersion() const; + QPDF_DLL + int getExtensionLevel(); + QPDF_DLL + QPDFObjectHandle getTrailer(); + QPDF_DLL + QPDFObjectHandle getRoot(); + QPDF_DLL + std::map getXRefTable(); + + // Public factory methods + + // Create a new stream. A subsequent call must be made to replaceStreamData() to provide data + // for the stream. The stream's dictionary may be retrieved by calling getDict(), and the + // resulting dictionary may be modified. Alternatively, you can create a new dictionary and + // call replaceDict to install it. + QPDF_DLL + QPDFObjectHandle newStream(); + + // Create a new stream. Use the given buffer as the stream data. The stream dictionary's + // /Length key will automatically be set to the size of the data buffer. If additional keys are + // required, the stream's dictionary may be retrieved by calling getDict(), and the resulting + // dictionary may be modified. This method is just a convenient wrapper around the newStream() + // and replaceStreamData(). It is a convenience methods for streams that require no parameters + // beyond the stream length. Note that you don't have to deal with compression yourself if you + // use QPDFWriter. By default, QPDFWriter will automatically compress uncompressed stream data. + // Example programs are provided that illustrate this. + QPDF_DLL + QPDFObjectHandle newStream(std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + QPDF_DLL + QPDFObjectHandle newStream(std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. + QPDF_DLL + QPDFObjectHandle newReserved(); + QPDF_DLL + QPDFObjectHandle newIndirectNull(); + + // Install this object handle as an indirect object and return an indirect reference to it. + QPDF_DLL + QPDFObjectHandle makeIndirectObject(QPDFObjectHandle); + + // Retrieve an object by object ID and generation. Returns an indirect reference to it. The + // getObject() methods were added for qpdf 11. + QPDF_DLL + QPDFObjectHandle getObject(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObject(int objid, int generation); + // These are older methods, but there is no intention to deprecate + // them. + QPDF_DLL + QPDFObjectHandle getObjectByObjGen(QPDFObjGen); + QPDF_DLL + QPDFObjectHandle getObjectByID(int objid, int generation); + + // Replace the object with the given object id with the given object. The object handle passed + // in must be a direct object, though it may contain references to other indirect objects within + // it. Prior to qpdf 10.2.1, after calling this method, existing QPDFObjectHandle instances that + // pointed to the original object still pointed to the original object, resulting in confusing + // and incorrect behavior. This was fixed in 10.2.1, so existing QPDFObjectHandle objects will + // start pointing to the newly replaced object. Note that replacing an object with + // QPDFObjectHandle::newNull() effectively removes the object from the file since a non-existent + // object is treated as a null object. To replace a reserved object, call replaceReserved + // instead. + QPDF_DLL + void replaceObject(QPDFObjGen og, QPDFObjectHandle); + QPDF_DLL + void replaceObject(int objid, int generation, QPDFObjectHandle); + + // Swap two objects given by ID. Prior to qpdf 10.2.1, existing QPDFObjectHandle instances that + // reference them objects not notice the swap, but this was fixed in 10.2.1. + QPDF_DLL + void swapObjects(QPDFObjGen og1, QPDFObjGen og2); + QPDF_DLL + void swapObjects(int objid1, int generation1, int objid2, int generation2); + + // Replace a reserved object. This is a wrapper around replaceObject but it guarantees that the + // underlying object is a reserved object or a null object. After this call, reserved will + // be a reference to replacement. + QPDF_DLL + void replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement); + + // Copy an object from another QPDF to this one. Starting with qpdf version 8.3.0, it is no + // longer necessary to keep the original QPDF around after the call to copyForeignObject as long + // as the source of any copied stream data is still available. Usually this means you just have + // to keep the input file around, not the QPDF object. The exception to this is if you copy a + // stream that gets its data from a QPDFObjectHandle::StreamDataProvider. In this case only, the + // original stream's QPDF object must stick around because the QPDF object is itself the source + // of the original stream data. For a more in-depth discussion, please see the TODO file. + // Starting in 8.4.0, you can call setImmediateCopyFrom(true) on the SOURCE QPDF object (the one + // you're copying FROM). If you do this prior to copying any of its objects, then neither the + // source QPDF object nor its input source needs to stick around at all regardless of the + // source. The cost is that the stream data is copied into RAM at the time copyForeignObject is + // called. See setImmediateCopyFrom for more information. + // + // The return value of this method is an indirect reference to the copied object in this file. + // This method is intended to be used to copy non-page objects. To copy page objects, pass the + // foreign page object directly to addPage (or addPageAt). If you copy objects that contain + // references to pages, you should copy the pages first using addPage(At). Otherwise references + // to the pages that have not been copied will be replaced with nulls. It is possible to use + // copyForeignObject on page objects if you are not going to use them as pages. Doing so copies + // the object normally but does not update the page structure. For example, it is a valid use + // case to use copyForeignObject for a page that you are going to turn into a form XObject, + // though you can also use QPDFPageObjectHelper::getFormXObjectForPage for that purpose. + // + // When copying objects with this method, object structure will be preserved, so all indirectly + // referenced indirect objects will be copied as well. This includes any circular references + // that may exist. The QPDF object keeps a record of what has already been copied, so shared + // objects will not be copied multiple times. This also means that if you mutate an object that + // has already been copied and try to copy it again, it won't work since the modified object + // will not be recopied. Therefore, you should do all mutation on the original file that you + // are going to do before you start copying its objects to a new file. + QPDF_DLL + QPDFObjectHandle copyForeignObject(QPDFObjectHandle foreign); + + // Encryption support + + enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes, e_aesv3 }; + + // To be removed from the public API in qpdf 13. See + // . + class EncryptionData + { + public: + // This class holds data read from the encryption dictionary. + EncryptionData( + int V, + int R, + int Length_bytes, + int P, + std::string const& O, + std::string const& U, + std::string const& OE, + std::string const& UE, + std::string const& Perms, + std::string const& id1, + bool encrypt_metadata) : + V(V), + R(R), + Length_bytes(Length_bytes), + P(P), + O(O), + U(U), + OE(OE), + UE(UE), + Perms(Perms), + id1(id1), + encrypt_metadata(encrypt_metadata) + { + } + + int getV() const; + int getR() const; + int getLengthBytes() const; + int getP() const; + std::string const& getO() const; + std::string const& getU() const; + std::string const& getOE() const; + std::string const& getUE() const; + std::string const& getPerms() const; + std::string const& getId1() const; + bool getEncryptMetadata() const; + + void setO(std::string const&); + void setU(std::string const&); + void setV5EncryptionParameters( + std::string const& O, + std::string const& OE, + std::string const& U, + std::string const& UE, + std::string const& Perms); + + private: + EncryptionData(EncryptionData const&) = delete; + EncryptionData& operator=(EncryptionData const&) = delete; + + int V; + int R; + int Length_bytes; + int P; + std::string O; + std::string U; + std::string OE; + std::string UE; + std::string Perms; + std::string id1; + bool encrypt_metadata; + }; + QPDF_DLL + bool isEncrypted() const; + + QPDF_DLL + bool isEncrypted(int& R, int& P); + + QPDF_DLL + bool isEncrypted( + int& R, + int& P, + int& V, + encryption_method_e& stream_method, + encryption_method_e& string_method, + encryption_method_e& file_method); + + QPDF_DLL + bool ownerPasswordMatched() const; + + QPDF_DLL + bool userPasswordMatched() const; + + // Encryption permissions -- not enforced by QPDF + QPDF_DLL + bool allowAccessibility(); + QPDF_DLL + bool allowExtractAll(); + QPDF_DLL + bool allowPrintLowRes(); + QPDF_DLL + bool allowPrintHighRes(); + QPDF_DLL + bool allowModifyAssembly(); + QPDF_DLL + bool allowModifyForm(); + QPDF_DLL + bool allowModifyAnnotation(); + QPDF_DLL + bool allowModifyOther(); + QPDF_DLL + bool allowModifyAll(); + + // Helper function to trim padding from user password. Calling trim_user_password on the result + // of getPaddedUserPassword gives getTrimmedUserPassword's result. + QPDF_DLL + static void trim_user_password(std::string& user_password); + QPDF_DLL + static std::string compute_data_key( + std::string const& encryption_key, + int objid, + int generation, + bool use_aes, + int encryption_V, + int encryption_R); + + // To be removed in qpdf 13. See . + [[deprecated("to be removed in qpdf 13")]] + QPDF_DLL static std::string + compute_encryption_key(std::string const& password, EncryptionData const& data); + + QPDF_DLL + static void compute_encryption_O_U( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& O, + std::string& U); + QPDF_DLL + static void compute_encryption_parameters_V5( + char const* user_password, + char const* owner_password, + int V, + int R, + int key_len, + int P, + bool encrypt_metadata, + std::string const& id1, + std::string& encryption_key, + std::string& O, + std::string& U, + std::string& OE, + std::string& UE, + std::string& Perms); + // Return the full user password as stored in the PDF file. For files encrypted with 40-bit or + // 128-bit keys, the user password can be recovered when the file is opened using the owner + // password. This is not possible with newer encryption formats. If you are attempting to + // recover the user password in a user-presentable form, call getTrimmedUserPassword() instead. + QPDF_DLL + std::string const& getPaddedUserPassword() const; + // Return human-readable form of user password subject to same limitations as + // getPaddedUserPassword(). + QPDF_DLL + std::string getTrimmedUserPassword() const; + // Return the previously computed or retrieved encryption key for this file + QPDF_DLL + std::string getEncryptionKey() const; + // Remove security restrictions associated with digitally signed files. From qpdf 11.7.0, this + // is called by QPDFAcroFormDocumentHelper::disableDigitalSignatures and is more useful when + // called from there than when just called by itself. + QPDF_DLL + void removeSecurityRestrictions(); + + // Linearization support + + // Returns true iff the file starts with a linearization parameter dictionary. Does no + // additional validation. + QPDF_DLL + bool isLinearized(); + + // Performs various sanity checks on a linearized file. Return true if no errors or warnings. + // Otherwise, return false and output errors and warnings to the default output stream + // (std::cout or whatever is configured in the logger). It is recommended for linearization + // errors to be treated as warnings. + QPDF_DLL + bool checkLinearization(); + + // Calls checkLinearization() and, if possible, prints normalized contents of some of the hints + // tables to the default output stream. Normalization includes adding min values to delta values + // and adjusting offsets based on the location and size of the primary hint stream. + QPDF_DLL + void showLinearizationData(); + + // Shows the contents of the cross-reference table + QPDF_DLL + void showXRefTable(); + + // Starting from qpdf 11.0 user code should not need to call this method. Before 11.0 this + // method was used to detect all indirect references to objects that don't exist and resolve + // them by replacing them with null, which is how the PDF spec says to interpret such dangling + // references. This method is called automatically when you try to add any new objects, if you + // call getAllObjects, and before a file is written. The qpdf object caches whether it has run + // this to avoid running it multiple times. Before 11.2.1 you could pass true to force it to run + // again if you had explicitly added new objects that may have additional dangling references. + QPDF_DLL + void fixDanglingReferences(bool force = false); + + // Return the approximate number of indirect objects. It is/ approximate because not all objects + // in the file are preserved in all cases, and gaps in object numbering are not preserved. + QPDF_DLL + size_t getObjectCount(); + + // Returns a list of indirect objects for every object in the xref table. Useful for discovering + // objects that are not otherwise referenced. + QPDF_DLL + std::vector getAllObjects(); + + // Optimization support -- see doc/optimization. Implemented in QPDF_optimization.cc + + // The object_stream_data map maps from a "compressed" object to the object stream that contains + // it. This enables optimize to populate the object <-> user maps with only uncompressed + // objects. If allow_changes is false, an exception will be thrown if any changes are made + // during the optimization process. This is available so that the test suite can make sure that + // a linearized file is already optimized. When called in this way, optimize() still populates + // the object <-> user maps. The optional skip_stream_parameters parameter, if present, is + // called for each stream object. The function should return 2 if optimization should discard + // /Length, /Filter, and /DecodeParms; 1 if it should discard /Length, and 0 if it should + // preserve all keys. This is used by QPDFWriter to avoid creation of dangling objects for + // stream dictionary keys it will be regenerating. + [[deprecated("Unused - see release notes for qpdf 12.1.0")]] QPDF_DLL void optimize( + std::map const& object_stream_data, + bool allow_changes = true, + std::function skip_stream_parameters = nullptr); + + // Traverse page tree return all /Page objects. It also detects and resolves cases in which the + // same /Page object is duplicated. For efficiency, this method returns a const reference to an + // internal vector of pages. Calls to addPage, addPageAt, and removePage safely update this, but + // direct manipulation of the pages tree or pushing inheritable objects to the page level may + // invalidate it. See comments for updateAllPagesCache() for additional notes. Newer code should + // use QPDFPageDocumentHelper::getAllPages instead. The decision to expose this internal cache + // was arguably incorrect, but it is being left here for compatibility. It is, however, + // completely safe to use this for files that you are not modifying. + QPDF_DLL + std::vector const& getAllPages(); + + QPDF_DLL + bool everCalledGetAllPages() const; + QPDF_DLL + bool everPushedInheritedAttributesToPages() const; + + // These methods, given a page object or its object/generation number, returns the 0-based index + // into the array returned by getAllPages() for that page. An exception is thrown if the page is + // not found. + QPDF_DLL + int findPage(QPDFObjGen og); + QPDF_DLL + int findPage(QPDFObjectHandle& page); + + // This method synchronizes QPDF's cache of the page structure with the actual /Pages tree. If + // you restrict changes to the /Pages tree, including addition, removal, or replacement of pages + // or changes to any /Pages objects, to calls to these page handling APIs, you never need to + // call this method. If you modify /Pages structures directly, you must call this method + // afterwards. This method updates the internal list of pages, so after calling this method, + // any previous references returned by getAllPages() will be valid again. It also resets any + // state about having pushed inherited attributes in /Pages objects down to the pages, so if you + // add any inheritable attributes to a /Pages object, you should also call this method. + QPDF_DLL + void updateAllPagesCache(); + + // Legacy handling API. These methods are not going anywhere, and you should feel free to + // continue using them if it simplifies your code. Newer code should make use of + // QPDFPageDocumentHelper instead as future page handling methods will be added there. The + // functionality and specification of these legacy methods is identical to the identically named + // methods there, except that these versions use QPDFObjectHandle instead of + // QPDFPageObjectHelper, so please see comments in that file for descriptions. There are + // subtleties you need to know about, so please look at the comments there. + QPDF_DLL + void pushInheritedAttributesToPage(); + QPDF_DLL + void addPage(QPDFObjectHandle newpage, bool first); + QPDF_DLL + void addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage); + QPDF_DLL + void removePage(QPDFObjectHandle page); + // End legacy page helpers + + // End of the public API. The following classes and methods are for qpdf internal use only. + + class Doc; + + inline Doc& doc(); + + // For testing only -- do not add to DLL + static bool test_json_validators(); + + private: + // It has never been safe to copy QPDF objects as there is code in the library that assumes + // there are no copies of a QPDF object. Copying QPDF objects was not prevented by the API until + // qpdf 11. If you have been copying QPDF objects, use std::shared_ptr instead. From qpdf + // 11, you can use QPDF::create to create them. + QPDF(QPDF const&) = delete; + QPDF& operator=(QPDF const&) = delete; + + static std::string const qpdf_version; + + class ObjCache; + class EncryptionParameters; + class StringDecrypter; + class ResolveRecorder; + class JSONReactor; + + void removeObject(QPDFObjGen og); + + // Calls finish() on the pipeline when done but does not delete it + bool pipeStreamData( + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + static bool pipeStreamData( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + QPDFObjGen og, + qpdf_offset_t offset, + size_t length, + QPDFObjectHandle dict, + bool is_root_metadata, + Pipeline* pipeline, + bool suppress_warnings, + bool will_retry); + + // methods to support encryption -- implemented in QPDF_encryption.cc + void initializeEncryption(); + static std::string + getKeyForObject(std::shared_ptr encp, QPDFObjGen og, bool use_aes); + void decryptString(std::string&, QPDFObjGen og); + static void decryptStream( + std::shared_ptr encp, + std::shared_ptr file, + QPDF& qpdf_for_warning, + Pipeline*& pipeline, + QPDFObjGen og, + QPDFObjectHandle& stream_dict, + bool is_root_metadata, + std::unique_ptr& heap); + + // JSON import + void importJSON(std::shared_ptr, bool must_be_complete); + + class Members; + + // Keep all member variables inside the Members object, which we dynamically allocate. This + // makes it possible to add new private members without breaking binary compatibility. + std::unique_ptr m; +}; + +#endif // QPDF_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFAcroFormDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFAcroFormDocumentHelper.hh new file mode 100644 index 0000000..935e161 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFAcroFormDocumentHelper.hh @@ -0,0 +1,234 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFACROFORMDOCUMENTHELPER_HH +#define QPDFACROFORMDOCUMENTHELPER_HH + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +// This document helper is intended to help with operations on interactive forms. Here are the key +// things to know: + +// * The PDF specification talks about interactive forms and also about form XObjects. While form +// XObjects appear in parts of interactive forms, this class is concerned about interactive forms, +// not form XObjects. +// +// * Interactive forms are discussed in the PDF Specification (ISO PDF 32000-1:2008) section 12.7. +// Also relevant is the section about Widget annotations. Annotations are discussed in section +// 12.5 with annotation dictionaries discussed in 12.5.1. Widget annotations are discussed +// specifically in section 12.5.6.19. +// +// * What you need to know about the structure of interactive forms in PDF files: +// +// - The document catalog contains the key "/AcroForm" which contains a list of fields. Fields are +// represented as a tree structure much like pages. Nodes in the fields tree may contain other +// fields. Fields may inherit values of many of their attributes from ancestors in the tree. +// +// - Fields may also have children that are widget annotations. As a special case, and a cause of +// considerable confusion, if a field has a single annotation as a child, the annotation +// dictionary may be merged with the field dictionary. In that case, the field and the +// annotation are in the same object. Note that, while field dictionary attributes are +// inherited, annotation dictionary attributes are not. +// +// - A page dictionary contains a key called "/Annots" which contains a simple list of +// annotations. For any given annotation of subtype "/Widget", you should encounter that +// annotation in the "/Annots" dictionary of a page, and you should also be able to reach it by +// traversing through the "/AcroForm" dictionary from the document catalog. In the simplest case +// (and also a very common case), a form field's widget annotation will be merged with the field +// object, and the object will appear directly both under "/Annots" in the page dictionary and +// under "/Fields" in the "/AcroForm" dictionary. In a more complex case, you may have to trace +// through various "/Kids" elements in the "/AcroForm" field entry until you find the annotation +// dictionary. +class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFAcroFormDocumentHelper& get(QPDF& qpdf); + + // Re-validate the AcroForm structure. This is useful if you have modified the structure of the + // AcroForm dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFAcroFormDocumentHelper(QPDF&); + + ~QPDFAcroFormDocumentHelper() override = default; + + // This class lazily creates an internal cache of the mapping among form fields, annotations, + // and pages. Methods within this class preserve the validity of this cache. However, if you + // modify pages' annotation dictionaries, the document's /AcroForm dictionary, or any form + // fields manually in a way that alters the association between forms, fields, annotations, and + // pages, it may cause this cache to become invalid. This method marks the cache invalid and + // forces it to be regenerated the next time it is needed. + QPDF_DLL + void invalidateCache(); + + QPDF_DLL + bool hasAcroForm(); + + // Add a form field, initializing the document's AcroForm dictionary if needed, updating the + // cache if necessary. Note that you are adding fields that are copies of other fields, this + // method may result in multiple fields existing with the same qualified name, which can have + // unexpected side effects. In that case, you should use addAndRenameFormFields() instead. + QPDF_DLL + void addFormField(QPDFFormFieldObjectHelper); + + // Add a collection of form fields making sure that their fully qualified names don't conflict + // with already present form fields. Fields within the collection of new fields that have the + // same name as each other will continue to do so. + QPDF_DLL + void addAndRenameFormFields(std::vector fields); + + // Remove fields from the fields array + QPDF_DLL + void removeFormFields(std::set const&); + + // Set the name of a field, updating internal records of field names. Name should be UTF-8 + // encoded. + QPDF_DLL + void setFormFieldName(QPDFFormFieldObjectHelper, std::string const& name); + + // Return a vector of all terminal fields in a document. Terminal fields are fields that have no + // children that are also fields. Terminal fields may still have children that are annotations. + // Intermediate nodes in the fields tree are not included in this list, but you can still reach + // them through the getParent method of the field object helper. + QPDF_DLL + std::vector getFormFields(); + + // Return all the form fields that have the given fully-qualified name and also have an explicit + // "/T" attribute. For this information to be accurate, any changes to field names must be done + // through setFormFieldName() above. + QPDF_DLL + std::set getFieldsWithQualifiedName(std::string const& name); + + // Return the annotations associated with a terminal field. Note that in the case of a field + // having a single annotation, the underlying object will typically be the same as the + // underlying object for the field. + QPDF_DLL + std::vector getAnnotationsForField(QPDFFormFieldObjectHelper); + + // Return annotations of subtype /Widget for a page. + QPDF_DLL + std::vector getWidgetAnnotationsForPage(QPDFPageObjectHelper); + + // Return top-level form fields for a page. + QPDF_DLL + std::vector getFormFieldsForPage(QPDFPageObjectHelper); + + // Return the terminal field that is associated with this annotation. If the annotation + // dictionary is merged with the field dictionary, the underlying object will be the same, but + // this is not always the case. Note that if you call this method with an annotation that is not + // a widget annotation, there will not be an associated field, and this method will return a + // helper associated with a null object (isNull() == true). + QPDF_DLL + QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper); + + // Return the current value of /NeedAppearances. If /NeedAppearances is missing, return false as + // that is how PDF viewers are supposed to interpret it. + QPDF_DLL + bool getNeedAppearances(); + + // Indicate whether appearance streams must be regenerated. If you modify a field value, you + // should call setNeedAppearances(true) unless you also generate an appearance stream for the + // corresponding annotation at the same time. If you generate appearance streams for all fields, + // you can call setNeedAppearances(false). If you use QPDFFormFieldObjectHelper::setV, it will + // automatically call this method unless you tell it not to. + QPDF_DLL + void setNeedAppearances(bool); + + // If /NeedAppearances is false, do nothing. Otherwise generate appearance streams for all + // widget annotations that need them. See comments in QPDFFormFieldObjectHelper.hh for + // generateAppearance for limitations. For checkbox and radio button fields, this code ensures + // that appearance state is consistent with the field's value and uses any pre-existing + // appearance streams. + QPDF_DLL + void generateAppearancesIfNeeded(); + + // Disable Digital Signature Fields. Remove all digital signature fields from the document, + // leaving any annotation showing the content of the field intact. This also calls + // QPDF::removeSecurityRestrictions. + QPDF_DLL + void disableDigitalSignatures(); + + // Note: this method works on all annotations, not just ones with associated fields. For each + // annotation in old_annots, apply the given transformation matrix to create a new annotation. + // New annotations are appended to new_annots. If the annotation is associated with a form + // field, a new form field is created that points to the new annotation and is appended to + // new_fields, and the old field is added to old_fields. + // + // old_annots may belong to a different QPDF object. In that case, you should pass in from_qpdf, + // and copyForeignObject will be called automatically. If this is the case, for efficiency, you + // may pass in a QPDFAcroFormDocumentHelper for the other file to avoid the expensive process of + // creating one for each call to transformAnnotations. New fields and annotations are not added + // to the document or pages. You have to do that yourself after calling transformAnnotations. If + // this operation will leave orphaned fields behind, such as if you are replacing the old + // annotations with the new ones on the same page and the fields and annotations are not shared, + // you will also need to remove the old fields to prevent them from hanging around unreferenced. + QPDF_DLL + void transformAnnotations( + QPDFObjectHandle old_annots, + std::vector& new_annots, + std::vector& new_fields, + std::set& old_fields, + QPDFMatrix const& cm, + QPDF* from_qpdf = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + // Copy form fields and annotations from one page to another, allowing the from page to be in a + // different QPDF or in the same QPDF. This would typically be called after calling addPage to + // add field/annotation awareness. When just copying the page by itself, annotations end up + // being shared, and fields end up being omitted because there is no reference to the field from + // the page. This method ensures that each separate copy of a page has private annotations and + // that fields and annotations are properly updated to resolve conflicts that may occur from + // common resource and field names across documents. It is basically a wrapper around + // transformAnnotations that handles updating the receiving page. If new_fields is non-null, any + // newly created fields are added to it. + QPDF_DLL + void fixCopiedAnnotations( + QPDFObjectHandle to_page, + QPDFObjectHandle from_page, + QPDFAcroFormDocumentHelper& from_afdh, + std::set* new_fields = nullptr); + + private: + friend class QPDF::Doc; + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFACROFORMDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFAnnotationObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFAnnotationObjectHelper.hh new file mode 100644 index 0000000..1f50d80 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFAnnotationObjectHelper.hh @@ -0,0 +1,105 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFANNOTATIONOBJECTHELPER_HH +#define QPDFANNOTATIONOBJECTHELPER_HH + +#include +#include + +#include + +class QPDFAnnotationObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFAnnotationObjectHelper(QPDFObjectHandle); + + ~QPDFAnnotationObjectHelper() override = default; + + // This class provides helper methods for annotations. More functionality will likely be added + // in the future. + + // Some functionality for annotations is also implemented in QPDFAcroFormDocumentHelper and + // QPDFFormFieldObjectHelper. In some cases, functions defined there work for other annotations + // besides widget annotations, but they are implemented with form fields so that they can + // properly handle form fields when needed. + + // Return the subtype of the annotation as a string (e.g. "/Widget"). Returns an empty string + // if the subtype (which is required by the spec) is missing. + QPDF_DLL + std::string getSubtype(); + + QPDF_DLL + QPDFObjectHandle::Rectangle getRect(); + + QPDF_DLL + QPDFObjectHandle getAppearanceDictionary(); + + // Return the appearance state as given in "/AS", or an empty string if none is given. + QPDF_DLL + std::string getAppearanceState(); + + // Return flags from "/F". The value is a logical or of pdf_annotation_flag_e as defined in + // qpdf/Constants.h. + QPDF_DLL + int getFlags(); + + // Return a specific stream. "which" may be one of "/N", "/R", or "/D" to indicate the normal, + // rollover, or down appearance stream. (Any value may be passed to "which"; if an appearance + // stream of that name exists, it will be returned.) If the value associated with "which" in the + // appearance dictionary is a subdictionary, an appearance state may be specified to select + // which appearance stream is desired. If not specified, the appearance state in "/AS" will + // used. + QPDF_DLL + QPDFObjectHandle getAppearanceStream(std::string const& which, std::string const& state = ""); + + // Generate text suitable for addition to the containing page's content stream that draws this + // annotation's appearance stream as a form XObject. The value "name" is the resource name that + // will be used to refer to the form xobject. The value "rotate" should be set to the page's + // /Rotate value or 0 if none. The values of required_flags and forbidden_flags are constructed + // by logically "or"ing annotation flags of type pdf_annotation_flag_e defined in + // qpdf/Constants.h. Content will be returned only if all required_flags are set and no + // forbidden_flags are set. For example, including an_no_view in forbidden_flags could be useful + // for creating an on-screen view, and including an_print to required_flags could be useful if + // preparing to print. + QPDF_DLL + std::string getPageContentForAppearance( + std::string const& name, + int rotate, + int required_flags = 0, + int forbidden_flags = an_invisible | an_hidden); + + private: + class Members + { + friend class QPDFAnnotationObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFANNOTATIONOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFCryptoImpl.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFCryptoImpl.hh new file mode 100644 index 0000000..34bbd98 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFCryptoImpl.hh @@ -0,0 +1,82 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFCRYPTOIMPL_HH +#define QPDFCRYPTOIMPL_HH + +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. +// Most users won't need to know or care about this class, but you can +// use it if you want to supply your own crypto implementation. To do +// so, provide an implementation of QPDFCryptoImpl, ensure that you +// register it by calling QPDFCryptoProvider::registerImpl, and make +// it the default by calling QPDFCryptoProvider::setDefaultProvider. +class QPDF_DLL_CLASS QPDFCryptoImpl +{ + public: + QPDFCryptoImpl() = default; + + virtual ~QPDFCryptoImpl() = default; + + // Random Number Generation + + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + // Hashing + + typedef unsigned char MD5_Digest[16]; + virtual void MD5_init() = 0; + virtual void MD5_update(unsigned char const* data, size_t len) = 0; + virtual void MD5_finalize() = 0; + virtual void MD5_digest(MD5_Digest) = 0; + + virtual void SHA2_init(int bits) = 0; + virtual void SHA2_update(unsigned char const* data, size_t len) = 0; + virtual void SHA2_finalize() = 0; + virtual std::string SHA2_digest() = 0; + + // Encryption/Decryption + + // QPDF must support RC4 to be able to work with older PDF files + // and readers. Search for RC4 in README.md + + // key_len of -1 means treat key_data as a null-terminated string + virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0; + // out_data = 0 means to encrypt/decrypt in place + virtual void + RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data = nullptr) = 0; + virtual void RC4_finalize() = 0; + + static size_t constexpr rijndael_buf_size = 16; + virtual void rijndael_init( + bool encrypt, + unsigned char const* key_data, + size_t key_len, + bool cbc_mode, + unsigned char* cbc_block) = 0; + virtual void rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0; + virtual void rijndael_finalize() = 0; +}; + +#endif // QPDFCRYPTOIMPL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFCryptoProvider.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFCryptoProvider.hh new file mode 100644 index 0000000..44d900c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFCryptoProvider.hh @@ -0,0 +1,107 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFCRYPTOPROVIDER_HH +#define QPDFCRYPTOPROVIDER_HH + +#include +#include +#include +#include +#include +#include +#include + +// This class is part of qpdf's pluggable crypto provider support. Most users won't need to know or +// care about this class, but you can use it if you want to supply your own crypto implementation. +// See also comments in QPDFCryptoImpl.hh. +class QPDFCryptoProvider +{ + public: + // Methods for getting and registering crypto implementations. These methods are not + // thread-safe. + + // Return an instance of a crypto provider using the default implementation. + QPDF_DLL + static std::shared_ptr getImpl(); + + // Return an instance of the crypto provider registered using the given name. + QPDF_DLL + static std::shared_ptr getImpl(std::string const& name); + + typedef std::function()> provider_fn; + + // Register a crypto implementation with the given name. The provider function must return + // a shared pointer to an instance of the implementation class, which must be derived from + // QPDFCryptoImpl. + QPDF_DLL static void registerImpl(std::string const& name, provider_fn f); + + // Register the given type (T) as a crypto implementation. T must be derived from QPDFCryptoImpl + // and must have a constructor that takes no arguments. + template + static void + registerImpl(std::string const& name) + { + registerImpl(name, std::make_shared); + } + + // Set the crypto provider registered with the given name as the default crypto implementation. + QPDF_DLL + static void setDefaultProvider(std::string const& name); + + // Get the names of registered implementations + QPDF_DLL + static std::set getRegisteredImpls(); + + // Get the name of the default crypto provider + QPDF_DLL + static std::string getDefaultProvider(); + + private: + QPDFCryptoProvider(); + ~QPDFCryptoProvider() = default; + QPDFCryptoProvider(QPDFCryptoProvider const&) = delete; + QPDFCryptoProvider& operator=(QPDFCryptoProvider const&) = delete; + + static QPDFCryptoProvider& getInstance(); + + std::shared_ptr getImpl_internal(std::string const& name) const; + void registerImpl_internal(std::string const& name, provider_fn f); + void setDefaultProvider_internal(std::string const& name); + + class Members + { + friend class QPDFCryptoProvider; + + public: + Members() = default; + ~Members() = default; + + private: + Members(Members const&) = delete; + Members& operator=(Members const&) = delete; + + std::string default_provider; + std::map providers; + }; + + std::shared_ptr m; +}; + +#endif // QPDFCRYPTOPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFDocumentHelper.hh new file mode 100644 index 0000000..67d42d4 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFDocumentHelper.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFDOCUMENTHELPER_HH +#define QPDFDOCUMENTHELPER_HH + +#include +#include + +// This is a base class for QPDF Document Helper classes. Document helpers are classes that provide +// a convenient, higher-level API for accessing document-level structures within a PDF file. +// Document helpers are always initialized with a reference to a QPDF object, and the object can +// always be retrieved. The intention is that you may freely intermix use of document helpers with +// the underlying QPDF object unless there is a specific comment in a specific helper method that +// says otherwise. The pattern of using helper objects was introduced to allow creation of higher +// level helper functions without polluting the public interface of QPDF. +class QPDF_DLL_CLASS QPDFDocumentHelper +{ + public: + QPDFDocumentHelper(QPDF& qpdf) : + qpdf(qpdf) + { + } + QPDF_DLL + virtual ~QPDFDocumentHelper(); + QPDF& + getQPDF() + { + return qpdf; + } + QPDF const& + getQPDF() const + { + return qpdf; + } + + protected: + QPDF& qpdf; +}; + +#endif // QPDFDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFEFStreamObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFEFStreamObjectHelper.hh new file mode 100644 index 0000000..fec2325 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFEFStreamObjectHelper.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEFSTREAMOBJECTHELPER_HH +#define QPDFEFSTREAMOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around Embedded File Streams, which are discussed in +// section 7.11.4 of the ISO-32000 PDF specification. +class QPDFEFStreamObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFEFStreamObjectHelper(QPDFObjectHandle); + + ~QPDFEFStreamObjectHelper() override = default; + + // Date parameters are strings that conform to the PDF spec for date/time strings, which is + // "D:yyyymmddhhmmss" where is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone + // offset. Examples: "D:20210207161528-05'00'", "D:20210207211528Z". See + // QUtil::qpdf_time_to_pdf_time. + + QPDF_DLL + std::string getCreationDate(); + QPDF_DLL + std::string getModDate(); + // Get size as reported in the object; return 0 if not present. + QPDF_DLL + size_t getSize(); + // Subtype is a mime type such as "text/plain" + QPDF_DLL + std::string getSubtype(); + // Return the checksum as stored in the object as a binary string. This does not check + // consistency with the data. If not present, return an empty string. The PDF spec specifies + // this as an MD5 checksum and notes that it is not to be used for security purposes since MD5 + // is known to be insecure. + QPDF_DLL + std::string getChecksum(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // efsoh.setCreationDate(x).setModDate(y); + + // Create a new embedded file stream with the given stream data, which can be provided in any of + // several ways. To get the new object back, call getObjectHandle() on the returned object. The + // checksum and size are computed automatically and stored. Other parameters may be supplied + // using setters defined below. + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::shared_ptr data); + QPDF_DLL + static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::string const& data); + // The provider function must write the data to the given pipeline. The function may be called + // multiple times by the qpdf library. You can pass QUtil::file_provider(filename) as the + // provider to have the qpdf library provide the contents of filename as a binary. + QPDF_DLL + static QPDFEFStreamObjectHelper + createEFStream(QPDF& qpdf, std::function provider); + + // Setters for other parameters + QPDF_DLL + QPDFEFStreamObjectHelper& setCreationDate(std::string const&); + QPDF_DLL + QPDFEFStreamObjectHelper& setModDate(std::string const&); + + // Set subtype as a mime-type, e.g. "text/plain" or "application/pdf". + QPDF_DLL + QPDFEFStreamObjectHelper& setSubtype(std::string const&); + + private: + QPDFObjectHandle getParam(std::string const& pkey); + void setParam(std::string const& pkey, QPDFObjectHandle const&); + static QPDFEFStreamObjectHelper newFromStream(QPDFObjectHandle stream); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEFSTREAMOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh new file mode 100644 index 0000000..12174d6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFEmbeddedFileDocumentHelper.hh @@ -0,0 +1,90 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEMBEDDEDFILEDOCUMENTHELPER_HH +#define QPDFEMBEDDEDFILEDOCUMENTHELPER_HH + +#include + +#include +#include +#include +#include + +#include +#include + +// This class provides a higher level interface around document-level file attachments, also known +// as embedded files. These are discussed in sections 7.7.4 and 7.11 of the ISO-32000 PDF +// specification. +class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the EmbeddedFiles structure, which can be expensive. + QPDF_DLL + static QPDFEmbeddedFileDocumentHelper& get(QPDF& qpdf); + + // Re-validate the EmbeddedFiles structure. This is useful if you have modified the structure of + // the EmbeddedFiles dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFEmbeddedFileDocumentHelper(QPDF&); + + ~QPDFEmbeddedFileDocumentHelper() override = default; + + QPDF_DLL + bool hasEmbeddedFiles() const; + + QPDF_DLL + std::map> getEmbeddedFiles(); + + // If an embedded file with the given name exists, return a (shared) pointer to it. Otherwise, + // return nullptr. + QPDF_DLL + std::shared_ptr getEmbeddedFile(std::string const& name); + + // Add or replace an attachment + QPDF_DLL + void replaceEmbeddedFile(std::string const& name, QPDFFileSpecObjectHelper const&); + + // Remove an embedded file if present. Return value is true if the file was present and was + // removed. This method not only removes the embedded file from the embedded files name tree but + // also nulls out the file specification dictionary. This means that any references to this file + // from file attachment annotations will also stop working. This is the best way to make the + // attachment actually disappear from the file and not just from the list of attachments. + QPDF_DLL + bool removeEmbeddedFile(std::string const& name); + + private: + void initEmbeddedFiles(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFEMBEDDEDFILEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFExc.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFExc.hh new file mode 100644 index 0000000..9038418 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFExc.hh @@ -0,0 +1,89 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFEXC_HH +#define QPDFEXC_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFExc: public std::runtime_error +{ + public: + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + QPDF_DLL + QPDFExc( + qpdf_error_code_e error_code, + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message, + bool zero_offset_valid); + + ~QPDFExc() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. Only the error code and message are + // guaranteed to have non-zero/empty values. + + // There is no lookup code that maps numeric error codes into strings. The numeric error code + // is just another way to get at the underlying issue, but it is more programmer-friendly than + // trying to parse a string that is subject to change. + + QPDF_DLL + qpdf_error_code_e getErrorCode() const; + QPDF_DLL + std::string const& getFilename() const; + QPDF_DLL + std::string const& getObject() const; + QPDF_DLL + qpdf_offset_t getFilePosition() const; + QPDF_DLL + std::string const& getMessageDetail() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat( + std::string const& filename, + std::string const& object, + qpdf_offset_t offset, + std::string const& message); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + qpdf_error_code_e error_code; + std::string filename; + std::string object; + qpdf_offset_t offset; + std::string message; +}; + +#endif // QPDFEXC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFFileSpecObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFFileSpecObjectHelper.hh new file mode 100644 index 0000000..9a00e20 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFFileSpecObjectHelper.hh @@ -0,0 +1,94 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFILESPECOBJECTHELPER_HH +#define QPDFFILESPECOBJECTHELPER_HH + +#include + +#include + +#include +#include + +// This class provides a higher level interface around File Specification dictionaries, which are +// discussed in section 7.11 of the ISO-32000 PDF specification. +class QPDFFileSpecObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFileSpecObjectHelper(QPDFObjectHandle); + + ~QPDFFileSpecObjectHelper() override = default; + + QPDF_DLL + std::string getDescription(); + + // Get the main filename for this file specification. In priority order, check /UF, /F, /Unix, + // /DOS, /Mac. + QPDF_DLL + std::string getFilename(); + + // Return any of /UF, /F, /Unix, /DOS, /Mac filename keys that may be present in the object. + QPDF_DLL + std::map getFilenames(); + + // Get the requested embedded file stream for this file specification. If key is empty, In + // priority order, check /UF, /F, /Unix, /DOS, /Mac. Returns a null object if not found. If this + // is an actual embedded file stream, its data is the content of the attachment. You can also + // use QPDFEFStreamObjectHelper for higher level access to the parameters. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStream(std::string const& key = ""); + + // Return the /EF key of the file spec, which is a map from file name key to embedded file + // stream. + QPDF_DLL + QPDFObjectHandle getEmbeddedFileStreams(); + + // Setters return a reference to this object so that they can be used as fluent interfaces, e.g. + // fsoh.setDescription(x).setFilename(y); + + // Create a new filespec as an indirect object with the given filename, and attach the contents + // of the specified file as data in an embedded file stream. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, std::string const& fullpath); + + // Create a new filespec as an indirect object with the given unicode filename and embedded file + // stream. The file name will be used as both /UF and /F. If you need to override, call + // setFilename. + QPDF_DLL + static QPDFFileSpecObjectHelper + createFileSpec(QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper); + + QPDF_DLL + QPDFFileSpecObjectHelper& setDescription(std::string const&); + // setFilename sets /UF to unicode_name. If compat_name is empty, it is also set to + // unicode_name. unicode_name should be a UTF-8 encoded string. compat_name is converted to a + // string QPDFObjectHandle literally, preserving whatever encoding it might happen to have. + QPDF_DLL + QPDFFileSpecObjectHelper& + setFilename(std::string const& unicode_name, std::string const& compat_name = ""); + + private: + class Members; + std::shared_ptr m; +}; + +#endif // QPDFFILESPECOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFFormFieldObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFFormFieldObjectHelper.hh new file mode 100644 index 0000000..a929563 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFFormFieldObjectHelper.hh @@ -0,0 +1,195 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFFORMFIELDOBJECTHELPER_HH +#define QPDFFORMFIELDOBJECTHELPER_HH + +#include + +#include +#include + +class QPDFAnnotationObjectHelper; + +// This object helper helps with form fields for interactive forms. Please see comments in +// QPDFAcroFormDocumentHelper.hh for additional details. +class QPDFFormFieldObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFFormFieldObjectHelper(); + QPDF_DLL + QPDFFormFieldObjectHelper(QPDFObjectHandle); + + ~QPDFFormFieldObjectHelper() override = default; + + QPDF_DLL + bool isNull(); + + // Return the field's parent. A form field object helper whose underlying object is null is + // returned if there is no parent. This condition may be tested by calling isNull(). + QPDF_DLL + QPDFFormFieldObjectHelper getParent(); + + // Return the top-level field for this field. Typically this will be the field itself or its + // parent. If is_different is provided, it is set to true if the top-level field is different + // from the field itself; otherwise it is set to false. + QPDF_DLL + QPDFFormFieldObjectHelper getTopLevelField(bool* is_different = nullptr); + + // Get a field value, possibly inheriting the value from an ancestor node. + QPDF_DLL + QPDFObjectHandle getInheritableFieldValue(std::string const& name); + + // Get an inherited field value as a string. If it is not a string, silently return the empty + // string. + QPDF_DLL + std::string getInheritableFieldValueAsString(std::string const& name); + + // Get an inherited field value of type name as a string representing the name. If it is not a + // name, silently return the empty string. + QPDF_DLL + std::string getInheritableFieldValueAsName(std::string const& name); + + // Returns the value of /FT if present, otherwise returns the empty string. + QPDF_DLL + std::string getFieldType(); + + QPDF_DLL + std::string getFullyQualifiedName(); + + QPDF_DLL + std::string getPartialName(); + + // Return the alternative field name (/TU), which is the field name intended to be presented to + // users. If not present, fall back to the fully qualified name. + QPDF_DLL + std::string getAlternativeName(); + + // Return the mapping field name (/TM). If not present, fall back to the alternative name, then + // to the partial name. + QPDF_DLL + std::string getMappingName(); + + QPDF_DLL + QPDFObjectHandle getValue(); + + // Return the field's value as a string. If this is called with a field whose value is not a + // string, the empty string will be silently returned. + QPDF_DLL + std::string getValueAsString(); + + QPDF_DLL + QPDFObjectHandle getDefaultValue(); + + // Return the field's default value as a string. If this is called with a field whose value is + // not a string, the empty string will be silently returned. + QPDF_DLL + std::string getDefaultValueAsString(); + + // Return the default appearance string, taking inheritance from the field tree into account. + // Returns the empty string if the default appearance string is not available (because it's + // erroneously absent or because this is not a variable text field). If not found in the field + // hierarchy, look in /AcroForm. + QPDF_DLL + std::string getDefaultAppearance(); + + // Return the default resource dictionary for the field. This comes not from the field but from + // the document-level /AcroForm dictionary. While several PDF generators put a /DR key in the + // form field's dictionary, experimentation suggests that many popular readers, including Adobe + // Acrobat and Acrobat Reader, ignore any /DR item on the field. + QPDF_DLL + QPDFObjectHandle getDefaultResources(); + + // Return the quadding value, taking inheritance from the field tree into account. Returns 0 if + // quadding is not specified. Look in /AcroForm if not found in the field hierarchy. + QPDF_DLL + int getQuadding(); + + // Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as defined in + // qpdf/Constants.h + QPDF_DLL + int getFlags(); + + // Methods for testing for particular types of form fields + + // Returns true if field is of type /Tx + QPDF_DLL + bool isText(); + // Returns true if field is of type /Btn and flags do not indicate some other type of button. + QPDF_DLL + bool isCheckbox(); + // Returns true if field is a checkbox and is checked. + QPDF_DLL + bool isChecked(); + // Returns true if field is of type /Btn and flags indicate that it is a radio button + QPDF_DLL + bool isRadioButton(); + // Returns true if field is of type /Btn and flags indicate that it is a pushbutton + QPDF_DLL + bool isPushbutton(); + // Returns true if field is of type /Ch + QPDF_DLL + bool isChoice(); + // Returns choices display values as UTF-8 strings + QPDF_DLL + std::vector getChoices(); + + // Set an attribute to the given value. If you have a QPDFAcroFormDocumentHelper and you want to + // set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, QPDFObjectHandle value); + + // Set an attribute to the given value as a Unicode string (UTF-16 BE encoded). The input string + // should be UTF-8 encoded. If you have a QPDFAcroFormDocumentHelper and you want to set the + // name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead. + QPDF_DLL + void setFieldAttribute(std::string const& key, std::string const& utf8_value); + + // Set /V (field value) to the given value. If need_appearances is true and the field type is + // either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this + // method not to set /NeedAppearances if you are going to generate an appearance stream + // yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes, + // radio buttons, pushbuttons) specially. When setting a checkbox value, any value other than + // /Off will be treated as on, and the actual value set will be based on the appearance stream's + // /N dictionary, so the value that ends up in /V may not exactly match the value you pass in. + QPDF_DLL + void setV(QPDFObjectHandle value, bool need_appearances = true); + + // Set /V (field value) to the given string value encoded as a Unicode string. The input value + // should be UTF-8 encoded. See comments above about /NeedAppearances. + QPDF_DLL + void setV(std::string const& utf8_value, bool need_appearances = true); + + // Update the appearance stream for this field. Note that qpdf's ability to generate appearance + // streams is limited. We only generate appearance streams for streams of type text or choice. + // The appearance uses the default parameters provided in the file, and it only supports ASCII + // characters. Quadding is currently ignored. While this functionality is limited, it should do + // a decent job on properly constructed PDF files when field values are restricted to ASCII + // characters. + QPDF_DLL + void generateAppearance(QPDFAnnotationObjectHelper&); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFFORMFIELDOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFJob.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFJob.hh new file mode 100644 index 0000000..cace443 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFJob.hh @@ -0,0 +1,542 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFJOB_HH +#define QPDFJOB_HH + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QPDFWriter; +class Pipeline; +class QPDFLogger; + +class QPDFJob +{ + public: + static int constexpr LATEST_JOB_JSON = 1; + + // Exit codes -- returned by getExitCode() after calling run() + static int constexpr EXIT_ERROR = qpdf_exit_error; + static int constexpr EXIT_WARNING = qpdf_exit_warning; + // For is-encrypted and requires-password + static int constexpr EXIT_IS_NOT_ENCRYPTED = qpdf_exit_is_not_encrypted; + static int constexpr EXIT_CORRECT_PASSWORD = qpdf_exit_correct_password; + + // QPDFUsage is thrown if there are any usage-like errors when calling Config methods. + QPDF_DLL + QPDFJob(); + + // SETUP FUNCTIONS + + // Initialize a QPDFJob object from argv, which must be a null-terminated array of + // null-terminated UTF-8-encoded C strings. The progname_env argument is the name of an + // environment variable which, if set, overrides the name of the executable for purposes of + // generating the --completion options. See QPDFArgParser for details. If a null pointer is + // passed in, the default value of "QPDF_EXECUTABLE" is used. This is used by the QPDF cli, + // which just initializes a QPDFJob from argv, calls run(), and handles errors and exit status + // issues. You can perform much of the cli functionality programmatically in this way rather + // than using the regular API. This is exposed in the C API, which makes it easier to get + // certain high-level qpdf functionality from other languages. If there are any command-line + // errors, this method will throw QPDFUsage which is derived from std::runtime_error. Other + // exceptions may be thrown in some cases. Note that argc, and argv should be UTF-8 encoded. If + // you are calling this from a Windows Unicode-aware main (wmain), see + // QUtil::call_main_from_wmain for information about converting arguments to UTF-8. This method + // will mutate arguments that are passed to it. + QPDF_DLL + void initializeFromArgv(char const* const argv[], char const* progname_env = nullptr); + + // Initialize a QPDFJob from json. Passing partial = true prevents this method from doing the + // final checks (calling checkConfiguration) after processing the json file. This makes it + // possible to initialize QPDFJob in stages using multiple json files or to have a json file + // that can be processed from the CLI with --job-json-file and be combined with other arguments. + // For example, you might include only encryption parameters, leaving it up to the rest of the + // command-line arguments to provide input and output files. initializeFromJson is called with + // partial = true when invoked from the command line. To make sure that the json file is fully + // valid on its own, just don't specify any other command-line flags. If there are any + // configuration errors, QPDFUsage is thrown. Some error messages may be CLI-centric. If an + // exception tells you to use the "--some-option" option, set the "someOption" key in the JSON + // object instead. + QPDF_DLL + void initializeFromJson(std::string const& json, bool partial = false); + + // Set name that is used to prefix verbose messages, progress messages, and other things that + // the library writes to output and error streams on the caller's behalf. Defaults to "qpdf". + QPDF_DLL + void setMessagePrefix(std::string const&); + QPDF_DLL + std::string getMessagePrefix() const; + + // To capture or redirect output, configure the logger returned by getLogger(). By default, all + // QPDF and QPDFJob objects share the global logger. If you need a private logger for some + // reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on + // configuring the logger. + // + // If you set a custom logger here, the logger will be passed to all subsequent QPDF objects + // created by this QPDFJob object. + QPDF_DLL + std::shared_ptr getLogger(); + QPDF_DLL + void setLogger(std::shared_ptr); + + // This deprecated method is the old way to capture output, but it didn't capture all output. + // See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it + // configures a private logger, separating this object from the default logger, and calls + // setOutputStreams on that logger. See QPDFLogger.hh for additional details. + [[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void + setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + // You can register a custom progress reporter to be called by QPDFWriter (see + // QPDFWriter::registerProgressReporter). This is only called if you also request progress + // reporting through normal configuration methods (e.g., pass --progress, call + // config()->progress, etc.) + QPDF_DLL + void registerProgressReporter(std::function); + + // Check to make sure no contradictory options have been specified. This is called automatically + // after initializing from argv or json and is also called by run, but you can call it manually + // as well. It throws a QPDFUsage exception if there are any errors. This Config object (see + // CONFIGURATION) also has a checkConfiguration method which calls this one. + QPDF_DLL + void checkConfiguration(); + + // Returns true if output is created by the specified job. + QPDF_DLL + bool createsOutput() const; + + // SEE BELOW FOR MORE PUBLIC METHODS AND CLASSES + private: + // These structures are private but we need to define them before the public Config classes. + struct CopyAttachmentFrom + { + std::string path; + std::string password; + std::string prefix; + }; + + struct AddAttachment + { + std::string path; + std::string key; + std::string filename; + std::string creationdate; + std::string moddate; + std::string mimetype; + std::string description; + bool replace{false}; + }; + + public: + // CONFIGURATION + + // Configuration classes are implemented in QPDFJob_config.cc. + + // The config() method returns a shared pointer to a Config object. The Config object contains + // methods that correspond with qpdf command-line arguments. You can use a fluent interface to + // configure a QPDFJob object that would do exactly the same thing as a specific qpdf command. + // The example qpdf-job.cc contains an example of this usage. You can also use + // initializeFromJson or initializeFromArgv to initialize a QPDFJob object. + + // Notes about the Config methods: + // + // * Most of the method declarations are automatically generated in header files that are + // included within the class definitions. They correspond in predictable ways to the + // command-line arguments and are generated from the same code that generates the command-line + // argument parsing code. + // + // * Methods return pointers, rather than references, to configuration objects. References + // might feel more familiar to users of fluent interfaces, so why do we use pointers? The + // main methods that create them return smart pointers so that users can initialize them when + // needed, which you can't do with references. Returning pointers instead of references makes + // for a more uniform interface. + + // Maintainer documentation: see the section in README-maintainer called "HOW TO ADD A + // COMMAND-LINE ARGUMENT", which contains references to additional places in the documentation. + + class Config; + + class AttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endAddAttachment(); + QPDF_DLL + AttConfig* file(std::string const& parameter); + +#include + + private: + AttConfig(Config*); + AttConfig(AttConfig const&) = delete; + + Config* config; + AddAttachment att; + }; + + class CopyAttConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endCopyAttachmentsFrom(); + QPDF_DLL + CopyAttConfig* file(std::string const& parameter); + +#include + + private: + CopyAttConfig(Config*); + CopyAttConfig(CopyAttConfig const&) = delete; + + Config* config; + CopyAttachmentFrom caf; + }; + + class PagesConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endPages(); + // From qpdf 11.9.0, you can call file(), range(), and password(). Each call to file() + // starts a new page spec. + QPDF_DLL + PagesConfig* pageSpec( + std::string const& filename, std::string const& range, char const* password = nullptr); + +#include + + private: + PagesConfig(Config*); + PagesConfig(PagesConfig const&) = delete; + + Config* config; + }; + + class UOConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endUnderlayOverlay(); + +#include + + private: + UOConfig(Config*); + UOConfig(UOConfig const&) = delete; + + Config* config; + }; + + class EncConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endEncrypt(); + QPDF_DLL + EncConfig* file(std::string const& parameter); + +#include + + private: + EncConfig(Config*); + EncConfig(EncConfig const&) = delete; + + Config* config; + }; + + class PageLabelsConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endSetPageLabels(); + +#include + + private: + PageLabelsConfig(Config*); + PageLabelsConfig(PageLabelsConfig const&) = delete; + + Config* config; + }; + + class GlobalConfig + { + friend class QPDFJob; + friend class Config; + + public: + QPDF_DLL + Config* endGlobal(); + +#include + + GlobalConfig(Config*); // for qpdf internal use only + GlobalConfig(GlobalConfig const&) = delete; + + private: + Config* config; + }; + + class Config + { + friend class QPDFJob; + + public: + // Proxy to QPDFJob::checkConfiguration() + QPDF_DLL + void checkConfiguration(); + + QPDF_DLL + Config* inputFile(std::string const& filename); + QPDF_DLL + Config* emptyInput(); + QPDF_DLL + Config* outputFile(std::string const& filename); + QPDF_DLL + Config* replaceInput(); + QPDF_DLL + Config* setPageLabels(std::vector const& specs); + + QPDF_DLL + std::shared_ptr copyAttachmentsFrom(); + QPDF_DLL + std::shared_ptr addAttachment(); + QPDF_DLL + std::shared_ptr global(); + QPDF_DLL + std::shared_ptr pages(); + QPDF_DLL + std::shared_ptr overlay(); + QPDF_DLL + std::shared_ptr underlay(); + QPDF_DLL + std::shared_ptr + encrypt(int keylen, std::string const& user_password, std::string const& owner_password); + +#include + + private: + Config() = delete; + Config(Config const&) = delete; + Config(QPDFJob& job) : + o(job) + { + } + QPDFJob& o; + }; + + // Return a top-level configuration item. See CONFIGURATION above for details. If an invalid + // configuration is created (such as supplying contradictory options, omitting an input file, + // etc.), QPDFUsage is thrown. Note that error messages are CLI-centric, but you can map them + // into config calls. For example, if an exception tells you to use the --some-option flag, you + // should call config()->someOption() instead. + QPDF_DLL + std::shared_ptr config(); + + // Execute the job + QPDF_DLL + void run(); + + // The following two methods allow a job to be run in two stages - creation of a QPDF object and + // writing of the QPDF object. This allows the QPDF object to be modified prior to writing it + // out. See examples/qpdfjob-remove-annotations for an illustration of its use. + + // Run the first stage of the job. Return a nullptr if the configuration is not valid. + QPDF_DLL + std::unique_ptr createQPDF(); + + // Run the second stage of the job. Do nothing if a nullptr is passed as parameter. + QPDF_DLL + void writeQPDF(QPDF& qpdf); + + // CHECK STATUS -- these methods provide information known after run() is called. + + QPDF_DLL + bool hasWarnings() const; + + // Return one of the EXIT_* constants defined at the top of the class declaration. This may be + // called after run() when run() did not throw an exception. Takes into consideration whether + // isEncrypted or requiresPassword was called. Note that this function does not know whether + // run() threw an exception, so code that uses this to determine how to exit should explicitly + // use EXIT_ERROR if run() threw an exception. + QPDF_DLL + int getExitCode() const; + + // Return value is bitwise OR of values from qpdf_encryption_status_e + QPDF_DLL + unsigned long getEncryptionStatus(); + + // HELPER FUNCTIONS -- methods useful for calling in handlers that interact with QPDFJob during + // run or initialization. + + // If in verbose mode, call the given function, passing in the output stream and message prefix. + QPDF_DLL + void doIfVerbose(std::function fn); + + // Provide a string that is the help information ("schema" for the qpdf-specific JSON object) + // for the specified version of JSON output. + QPDF_DLL + static std::string json_out_schema(int version); + + [[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL json_out_schema_v1(); + + // Provide a string that is the help information for specified version of JSON format for + // QPDFJob. + QPDF_DLL + static std::string job_json_schema(int version); + + [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1(); + + private: + struct PageNo; + struct Selection; + struct Input; + struct Inputs; + struct RotationSpec; + struct UnderOverlay; + struct PageLabelSpec; + + enum password_mode_e { pm_bytes, pm_hex_bytes, pm_unicode, pm_auto }; + + // Helper functions + static void usage(std::string const& msg); + static JSON json_schema(int json_version, std::set* keys = nullptr); + static void parse_object_id(std::string const& objspec, bool& trailer, int& obj, int& gen); + void parseRotationParameter(std::string const&); + std::vector parseNumrange(char const* range, int max); + + // Basic file processing + void processFile( + std::unique_ptr&, + char const* filename, + char const* password, + bool used_for_input, + bool main_input); + void processInputSource( + std::unique_ptr&, + std::shared_ptr is, + char const* password, + bool used_for_input); + void doProcess( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + void doProcessOnce( + std::unique_ptr&, + std::function fn, + char const* password, + bool empty, + bool used_for_input, + bool main_input); + + // Transformations + void handlePageSpecs(QPDF& pdf); + bool shouldRemoveUnreferencedResources(QPDF& pdf); + void handleRotations(QPDF& pdf); + void getUOPagenos( + std::vector& uo, std::vector>>& pagenos); + void handleUnderOverlay(QPDF& pdf); + std::string doUnderOverlayForPage( + QPDF& pdf, + UnderOverlay& uo, + std::vector>>& pagenos, + PageNo const& page_idx, + size_t uo_idx, + std::map>& fo, + QPDFPageObjectHelper& dest_page); + void validateUnderOverlay(QPDF& pdf, UnderOverlay* uo); + void handleTransformations(QPDF& pdf); + void addAttachments(QPDF& pdf); + void copyAttachments(QPDF& pdf); + + // Inspection + void doInspection(QPDF& pdf); + void doCheck(QPDF& pdf); + void showEncryption(QPDF& pdf); + void doShowObj(QPDF& pdf); + void doShowPages(QPDF& pdf); + void doListAttachments(QPDF& pdf); + void doShowAttachment(QPDF& pdf); + + // Output generation + void doSplitPages(QPDF& pdf); + void setWriterOptions(qpdf::Writer&); + void setEncryptionOptions(QPDFWriter&); + void maybeFixWritePassword(int R, std::string& password); + void writeOutfile(QPDF& pdf); + void writeJSON(QPDF& pdf); + + // JSON + void doJSON(QPDF& pdf, Pipeline*); + QPDFObjGen::set getWantedJSONObjects(); + void doJSONObjects(Pipeline* p, bool& first, QPDF& pdf); + void doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPages(Pipeline* p, bool& first, QPDF& pdf); + void doJSONPageLabels(Pipeline* p, bool& first, QPDF& pdf); + void doJSONOutlines(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAcroform(Pipeline* p, bool& first, QPDF& pdf); + void doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf); + void doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf); + void addOutlinesToJson( + std::vector outlines, + JSON& j, + std::map& page_numbers); + + enum remove_unref_e { re_auto, re_yes, re_no }; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOBJECT_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFLogger.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFLogger.hh new file mode 100644 index 0000000..1e360be --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFLogger.hh @@ -0,0 +1,164 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFLOGGER_HH +#define QPDFLOGGER_HH + +#include +#include +#include +#include + +class QPDFLogger +{ + public: + QPDF_DLL + static std::shared_ptr create(); + + // Return the default logger. In general, you should use the default logger. You can also create + // your own loggers and use them with QPDF and QPDFJob objects, but there are few reasons to do + // so. One reason may be that you are using multiple QPDF or QPDFJob objects in different + // threads and want to capture output and errors to different streams. (Note that a single QPDF + // or QPDFJob can't be safely used from multiple threads, but it is safe to use separate QPDF + // and QPDFJob objects on separate threads.) Another possible reason would be if you are writing + // an application that uses the qpdf library directly and qpdf is also used by a downstream + // library or if you are using qpdf from a library and don't want to interfere with potential + // uses of qpdf by other libraries or applications. + QPDF_DLL + static std::shared_ptr defaultLogger(); + + // Defaults: + // + // info -- if save is standard output, standard error, else standard output + // warn -- whatever error points to + // error -- standard error + // save -- undefined unless set + // + // "info" is used for diagnostic messages, verbose messages, and progress messages. "warn" is + // used for warnings. "error" is used for errors. "save" is used for saving output -- see below. + // + // On deletion, finish() is called for the standard output and standard error pipelines, which + // flushes output. If you supply any custom pipelines, you must call finish() on them yourself. + // Note that calling finish is not needed for string, stdio, or ostream pipelines. + // + // NOTES ABOUT THE SAVE PIPELINE + // + // The save pipeline is used by QPDFJob when some kind of binary output is being saved. This + // includes saving attachments and stream data and also includes when the output file is + // standard output. If you want to grab that output, you can call setSave. See + // examples/qpdfjob-save-attachment.cc and examples/qpdfjob-c-save-attachment.c. + // + // You should never set the save pipeline to the same destination as something else. Doing so + // will corrupt your save output. If you want to save to standard output, use the method + // saveToStandardOutput(). In addition to setting the save pipeline, that does the following + // extra things: + // + // * If standard output has been used, a logic error is thrown + // * If info is set to standard output at the time of the set save call, it is switched to + // standard error. + // + // This is not a guarantee. You can still mess this up in ways that are not checked. Here are a + // few examples: + // + // * Don't set any pipeline to standard output *after* passing it to setSave() + // * Don't use a separate mechanism to write stdout/stderr other than + // QPDFLogger::standardOutput() + // * Don't set anything to the same custom pipeline that save is set to. + // + // Just be sure that if you change pipelines around, you should avoid having the save pipeline + // also be used for any other purpose. The special case for saving to standard output allows you + // to call saveToStandardOutput() early without having to worry about the info pipeline. + + QPDF_DLL + void info(char const*); + QPDF_DLL + void info(std::string const&); + QPDF_DLL + std::shared_ptr getInfo(bool null_okay = false); + + QPDF_DLL + void warn(char const*); + QPDF_DLL + void warn(std::string const&); + QPDF_DLL + std::shared_ptr getWarn(bool null_okay = false); + + QPDF_DLL + void error(char const*); + QPDF_DLL + void error(std::string const&); + QPDF_DLL + std::shared_ptr getError(bool null_okay = false); + + QPDF_DLL + std::shared_ptr getSave(bool null_okay = false); + + QPDF_DLL + std::shared_ptr standardOutput(); + QPDF_DLL + std::shared_ptr standardError(); + QPDF_DLL + std::shared_ptr discard(); + + // Passing a null pointer resets to default + QPDF_DLL + void setInfo(std::shared_ptr); + QPDF_DLL + void setWarn(std::shared_ptr); + QPDF_DLL + void setError(std::shared_ptr); + // See notes above about the save pipeline + QPDF_DLL + void setSave(std::shared_ptr, bool only_if_not_set); + QPDF_DLL + void saveToStandardOutput(bool only_if_not_set); + + // Shortcut for logic to reset output to new output/error streams. out_stream is used for info, + // err_stream is used for error, and warning is cleared so that it follows error. + QPDF_DLL + void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); + + private: + QPDFLogger(); + std::shared_ptr throwIfNull(std::shared_ptr, bool null_okay); + + class Members + { + friend class QPDFLogger; + + public: + ~Members(); + + private: + Members(); + Members(Members const&) = delete; + + std::shared_ptr p_discard; + std::shared_ptr p_real_stdout; + std::shared_ptr p_stdout; + std::shared_ptr p_stderr; + std::shared_ptr p_info; + std::shared_ptr p_warn; + std::shared_ptr p_error; + std::shared_ptr p_save; + }; + std::shared_ptr m; +}; + +#endif // QPDFLOGGER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFMatrix.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFMatrix.hh new file mode 100644 index 0000000..37624df --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFMatrix.hh @@ -0,0 +1,93 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFMATRIX_HH +#define QPDFMATRIX_HH + +#include +#include +#include + +// This class represents a PDF transformation matrix using a tuple such that +// +// ┌ ┐ +// │ a b 0 │ +// (a, b, c, d, e, f) = │ c d 0 │ +// │ e f 1 │ +// └ ┘ +class QPDFMatrix +{ + public: + QPDF_DLL + QPDFMatrix(); + QPDF_DLL + QPDFMatrix(double a, double b, double c, double d, double e, double f); + QPDF_DLL + QPDFMatrix(QPDFObjectHandle::Matrix const&); + + // Returns the six values separated by spaces as real numbers with trimmed zeroes. + QPDF_DLL + std::string unparse() const; + + QPDF_DLL + QPDFObjectHandle::Matrix getAsMatrix() const; + + // Replace this with other * this + QPDF_DLL + void concat(QPDFMatrix const& other); + + // Same as concat(sx, 0, 0, sy, 0, 0) + QPDF_DLL + void scale(double sx, double sy); + + // Same as concat(1, 0, 0, 1, tx, ty); + QPDF_DLL + void translate(double tx, double ty); + + // Any value other than 90, 180, or 270 is ignored + QPDF_DLL + void rotatex90(int angle); + + // Transform a point. The underlying operation is to take + // [x y 1] * this + // and take the first and second rows of the result as xp and yp. + QPDF_DLL + void transform(double x, double y, double& xp, double& yp) const; + + // Transform a rectangle by creating a new rectangle that tightly bounds the polygon resulting + // from transforming the four corners. + QPDF_DLL + QPDFObjectHandle::Rectangle transformRectangle(QPDFObjectHandle::Rectangle r) const; + + // operator== tests for exact equality, not considering deltas for floating point. + QPDF_DLL + bool operator==(QPDFMatrix const& rhs) const; + + QPDF_DLL + bool operator!=(QPDFMatrix const& rhs) const; + + double a; + double b; + double c; + double d; + double e; + double f; +}; + +#endif // QPDFMATRIX_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFNameTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFNameTreeObjectHelper.hh new file mode 100644 index 0000000..7677819 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFNameTreeObjectHelper.hh @@ -0,0 +1,184 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNAMETREEOBJECTHELPER_HH +#define QPDFNAMETREEOBJECTHELPER_HH + +#include +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for name trees. See section 7.9.6 in the PDF spec (ISO 32000) for a +// description of name trees. When looking up items in the name tree, use UTF-8 strings. All names +// are normalized for lookup purposes. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNameTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNameTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Create an empty name tree + QPDF_DLL + static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + QPDF_DLL + ~QPDFNameTreeObjectHelper() override; + + // Return whether the name tree has an explicit entry for this name. + QPDF_DLL + bool hasName(std::string const& utf8); + + // Find an object by name. If found, returns true and initializes oh. See also find(). + QPDF_DLL + bool findObject(std::string const& utf8, QPDFObjectHandle& oh); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNameTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(std::string const& key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a string and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(std::string const& key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(std::string const& key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(std::string const& key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the name tree as a map. Note that name trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNameTreeObjectHelper's iterator. + QPDF_DLL + std::map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNAMETREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFNumberTreeObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFNumberTreeObjectHelper.hh new file mode 100644 index 0000000..b7d7716 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFNumberTreeObjectHelper.hh @@ -0,0 +1,200 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFNUMBERTREEOBJECTHELPER_HH +#define QPDFNUMBERTREEOBJECTHELPER_HH + +#include +#include +#include +#include + +#include + +class NNTreeImpl; +class NNTreeIterator; +class NNTreeDetails; + +// This is an object helper for number trees. See section 7.9.7 in the PDF spec (ISO 32000) for a +// description of number trees. +// +// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNumberTreeObjectHelper. +class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper +{ + public: + // The qpdf object is required so that this class can issue warnings, attempt repairs, and add + // indirect objects. + QPDF_DLL + QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true); + + QPDF_DLL + QPDFNumberTreeObjectHelper( + QPDFObjectHandle, + QPDF&, + std::function value_validator, + bool auto_repair); + + QPDF_DLL + ~QPDFNumberTreeObjectHelper() override; + + // Create an empty number tree + QPDF_DLL + static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true); + + typedef long long int numtree_number; + + // Validate the name tree. Returns true if the tree is valid. + // + // If the tree is not valid and auto_repair is true, attempt to repair the tree. + QPDF_DLL + bool validate(bool repair = true); + + // Return overall minimum and maximum indices + QPDF_DLL + numtree_number getMin(); + QPDF_DLL + numtree_number getMax(); + + // Return whether the number tree has an explicit entry for this number. + QPDF_DLL + bool hasIndex(numtree_number idx); + + // Find an object with a specific index. If found, returns true and initializes oh. See also + // find(). + QPDF_DLL + bool findObject(numtree_number idx, QPDFObjectHandle& oh); + // Find the object at the index or, if not found, the object whose index is the highest index + // less than the requested index. If the requested index is less than the minimum, return false. + // Otherwise, return true, initialize oh to the object, and set offset to the difference between + // the requested index and the actual index. For example, if a number tree has values for 3 and + // 6 and idx is 5, this method would return true, initialize oh to the value with index 3, and + // set offset to 2 (5 - 3). See also find(). + QPDF_DLL + bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset); + + class QPDF_DLL_PRIVATE iterator + { + friend class QPDFNumberTreeObjectHelper; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + bool valid() const; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + // DANGER: this method can create inconsistent trees if not used properly! Insert a new item + // immediately after the current iterator and increment so that it points to the new item. + // If the current iterator is end(), insert at the beginning. This method does not check for + // proper ordering, so if you use it, you must ensure that the item you are inserting + // belongs where you are putting it. The reason for this method is that it is more efficient + // than insert() and can be used safely when you are creating a new tree and inserting items + // in sorted order. + QPDF_DLL + void insertAfter(numtree_number key, QPDFObjectHandle value); + + // Remove the current item and advance the iterator to the next item. + QPDF_DLL + void remove(); + + private: + void updateIValue(); + + iterator(std::shared_ptr const&); + std::shared_ptr impl; + value_type ivalue; + }; + + // The iterator looks like map iterator, so i.first is a numtree_number and i.second is a + // QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings + // you to the last item. + QPDF_DLL + iterator begin() const; + QPDF_DLL + iterator end() const; + // Return a bidirectional iterator that points to the last item. + QPDF_DLL + iterator last() const; + + // Find the entry with the given key. If return_prev_if_not_found is true and the item is not + // found, return the next lower item. + QPDF_DLL + iterator find(numtree_number key, bool return_prev_if_not_found = false); + + // Insert a new item. If the key already exists, it is replaced. + QPDF_DLL + iterator insert(numtree_number key, QPDFObjectHandle value); + + // Remove an item. Return true if the item was found and removed; otherwise return false. If + // value is not nullptr, initialize it to the value that was removed. + QPDF_DLL + bool remove(numtree_number key, QPDFObjectHandle* value = nullptr); + + // Return the contents of the number tree as a map. Note that number trees may be very large, so + // this may use a lot of RAM. It is more efficient to use QPDFNumberTreeObjectHelper's iterator. + typedef std::map idx_map; + QPDF_DLL + idx_map getAsMap() const; + + // Split a node if the number of items exceeds this value. There's no real reason to ever set + // this except for testing. + QPDF_DLL + void setSplitThreshold(int); + + private: + class QPDF_DLL_PRIVATE Members; + + std::shared_ptr m; +}; + +#endif // QPDFNUMBERTREEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjGen.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjGen.hh new file mode 100644 index 0000000..1f92488 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjGen.hh @@ -0,0 +1,137 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJGEN_HH +#define QPDFOBJGEN_HH + +#include + +#include +#include +#include + +class QPDFObjectHandle; +class QPDFObjectHelper; + +// This class represents an object ID and generation pair. It is suitable to use as a key in a map +// or set. + +class QPDFObjGen +{ + public: + QPDFObjGen() = default; + QPDFObjGen(int obj, int gen) : + obj(obj), + gen(gen) + { + } + bool + operator<(QPDFObjGen const& rhs) const + { + return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen); + } + bool + operator==(QPDFObjGen const& rhs) const + { + return obj == rhs.obj && gen == rhs.gen; + } + bool + operator!=(QPDFObjGen const& rhs) const + { + return !(*this == rhs); + } + int + getObj() const + { + return obj; + } + int + getGen() const + { + return gen; + } + bool + isIndirect() const + { + return obj != 0; + } + std::string + unparse(char separator = ',') const + { + return std::to_string(obj) + separator + std::to_string(gen); + } + friend std::ostream& + operator<<(std::ostream& os, QPDFObjGen og) + { + os << og.obj << "," << og.gen; + return os; + } + + // Convenience class for loop detection when processing objects. + // + // The class adds 'add' methods to a std::set which allows to test whether an + // QPDFObjGen is present in the set and to insert it in a single operation. The 'add' method is + // overloaded to take a QPDFObjGen, QPDFObjectHandle or an QPDFObjectHelper as parameter. + // + // The erase method is modified to ignore requests to erase QPDFObjGen(0, 0). + // + // Usage example: + // + // void process_object(QPDFObjectHandle oh, QPDFObjGen::set& seen) + // { + // if (seen.add(oh)) { + // // handle first encounter of oh + // } else { + // // handle loop / subsequent encounter of oh + // } + // } + class QPDF_DLL_CLASS set: public std::set + { + public: + // Add 'og' to the set. Return false if 'og' is already present in the set. Attempts to + // insert QPDFObjGen(0, 0) are ignored. + bool + add(QPDFObjGen og) + { + if (og.isIndirect()) { + if (count(og)) { + return false; + } + emplace(og); + } + return true; + } + + void + erase(QPDFObjGen og) + { + if (og.isIndirect()) { + std::set::erase(og); + } + } + }; + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created and destroyed. + int obj{0}; + int gen{0}; +}; + +#endif // QPDFOBJGEN_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObject.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObject.hh new file mode 100644 index 0000000..8499637 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObject.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECT_OLD_HH +#define QPDFOBJECT_OLD_HH + +// Current code should not include . This file exists +// to ensure that code that includes it doesn't accidentally work because +// of an old qpdf installed on the system. Including this file became an +// error with qpdf version 12. The internal QPDFObject API is defined in +// QPDFObject_private.hh, which is not part of the public API. + +// Instead of including this header, include , and +// replace `QPDFObject::ot_` with `::ot_` in your code. +#error "QPDFObject.hh is obsolete; see comments in QPDFObject.hh for details" + +#endif // QPDFOBJECT_OLD_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjectHandle.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjectHandle.hh new file mode 100644 index 0000000..9fef4e6 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjectHandle.hh @@ -0,0 +1,1576 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFOBJECTHANDLE_HH +#define QPDFOBJECTHANDLE_HH + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class Pipeline; +class QPDF_Array; +class QPDF_Bool; +class QPDF_Dictionary; +class QPDF_InlineImage; +class QPDF_Integer; +class QPDF_Name; +class QPDF_Null; +class QPDF_Operator; +class QPDF_Real; +class QPDF_Reserved; +class QPDF_Stream; +class QPDF_String; +class QPDFObject; +class QPDFObjectHandle; +class QPDFTokenizer; +class QPDFExc; +class Pl_QPDFTokenizer; +class QPDFMatrix; +namespace qpdf::impl +{ + class Parser; +} + +class QPDFObjectHandle: public qpdf::BaseHandle +{ + friend class qpdf::impl::Parser; + + public: + // This class is used by replaceStreamData. It provides an alternative way of associating + // stream data with a stream. See comments on replaceStreamData and newStream for additional + // details. + class QPDF_DLL_CLASS StreamDataProvider + { + public: + QPDF_DLL + StreamDataProvider(bool supports_retry = false); + + QPDF_DLL + virtual ~StreamDataProvider(); + // The implementation of this function must write stream data to the given pipeline. The + // stream data must conform to whatever filters are explicitly associated with the stream. + // QPDFWriter may, in some cases, add compression, but if it does, it will update the + // filters as needed. Every call to provideStreamData for a given stream must write the same + // data. Note that, when writing linearized files, qpdf will call your provideStreamData + // twice, and if it generates different output, you risk generating invalid output or having + // qpdf throw an exception. The object ID and generation passed to this method are those + // that belong to the stream on behalf of which the provider is called. They may be ignored + // or used by the implementation for indexing or other purposes. This information is made + // available just to make it more convenient to use a single StreamDataProvider object to + // provide data for multiple streams. + + // A few things to keep in mind: + // + // * Stream data providers must not modify any objects since they may be called after some + // parts of the file have already been written. + // + // * Since qpdf may call provideStreamData multiple times when writing linearized files, if + // the work done by your stream data provider is slow or computationally intensive, you + // might want to implement your own cache. + // + // * Once you have called replaceStreamData, the original stream data is no longer directly + // accessible from the stream, but this is easy to work around by copying the stream to + // a separate QPDF object. The qpdf library implements this very efficiently without + // actually making a copy of the stream data. You can find examples of this pattern in + // some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc. + + // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or + // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by + // allowing an alternative provideStreamData to be implemented. You must implement at least + // one of the versions of provideStreamData below. If you implement the version that + // supports retry and returns a value, you should pass true as the value of supports_retry + // in the base class constructor. This will cause the library to call that version of the + // method, which should also return a boolean indicating whether it ran without errors. + QPDF_DLL + virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline); + QPDF_DLL + virtual bool provideStreamData( + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline); + QPDF_DLL virtual bool provideStreamData( + int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry); + QPDF_DLL + bool supportsRetry(); + + private: + bool supports_retry; + }; + + // The TokenFilter class provides a way to filter content streams in a lexically aware fashion. + // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter + // methods or can be applied on the spot by filterPageContents. You may also use + // Pl_QPDFTokenizer directly if you need full control. + // + // The handleToken method is called for each token, including the eof token, and then handleEOF + // is called at the very end. Handlers may call write (or writeToken) to pass data downstream. + // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of + // using TokenFilters. + // + // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you + // get the canonical, "parsed" representation of the token. For a string, this means that there + // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits) + // has been resolved. qpdf's internal representation of a name includes the leading slash. As + // such, you can't write the value of token.getValue() directly to output that is supposed to be + // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can + // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new + // string or name token from a canonical representation, use + // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or + // QPDFTokenizer::Token(QPDFTokenizer::tt_name, + // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can + // still write them with writeToken(). Example: + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain")) + // would write `/text#2fplain`, and + // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`. + class QPDF_DLL_CLASS TokenFilter + { + public: + TokenFilter() = default; + virtual ~TokenFilter() = default; + virtual void handleToken(QPDFTokenizer::Token const&) = 0; + QPDF_DLL + virtual void handleEOF(); + + class PipelineAccessor + { + friend class Pl_QPDFTokenizer; + + private: + static void + setPipeline(TokenFilter* f, Pipeline* p) + { + f->setPipeline(p); + } + }; + + protected: + QPDF_DLL + void write(char const* data, size_t len); + QPDF_DLL + void write(std::string const& str); + QPDF_DLL + void writeToken(QPDFTokenizer::Token const&); + + private: + QPDF_DLL_PRIVATE + void setPipeline(Pipeline*); + + Pipeline* pipeline; + }; + + // This class is used by parse to decrypt strings when reading an object that contains encrypted + // strings. + class StringDecrypter + { + public: + virtual ~StringDecrypter() = default; + virtual void decryptString(std::string& val) = 0; + }; + + // This class is used by parsePageContents. Callers must instantiate a subclass of this with + // handlers defined to accept QPDFObjectHandles that are parsed from the stream. + class QPDF_DLL_CLASS ParserCallbacks + { + public: + virtual ~ParserCallbacks() = default; + // One of the handleObject methods must be overridden. + QPDF_DLL + virtual void handleObject(QPDFObjectHandle); + QPDF_DLL + virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length); + + virtual void handleEOF() = 0; + + // Override this if you want to know the full size of the contents, possibly after + // concatenation of multiple streams. This is called before the first call to handleObject. + QPDF_DLL + virtual void contentSize(size_t); + + protected: + // Implementors may call this method during parsing to terminate parsing early. This method + // throws an exception that is caught by parsePageContents, so its effect is immediate. + QPDF_DLL + void terminateParsing(); + }; + + // Convenience object for rectangles + class Rectangle + { + public: + Rectangle() : + llx(0.0), + lly(0.0), + urx(0.0), + ury(0.0) + { + } + Rectangle(double llx, double lly, double urx, double ury) : + llx(llx), + lly(lly), + urx(urx), + ury(ury) + { + } + + double llx; + double lly; + double urx; + double ury; + }; + + // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't + // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity + // transform matrix and this one is all zeroes. + class Matrix + { + public: + Matrix() : + a(0.0), + b(0.0), + c(0.0), + d(0.0), + e(0.0), + f(0.0) + { + } + Matrix(double a, double b, double c, double d, double e, double f) : + a(a), + b(b), + c(c), + d(d), + e(e), + f(f) + { + } + + double a; + double b; + double c; + double d; + double e; + double f; + }; + + QPDFObjectHandle() = default; + QPDFObjectHandle(QPDFObjectHandle const&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default; + QPDFObjectHandle(QPDFObjectHandle&&) = default; + QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default; + + // This method is provided for backward compatibility only. New code should convert to bool + // instead. + inline bool isInitialized() const; + + // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying + // object, meaning that changes to one are reflected in the other, or "if you paint one, the + // other one changes color." This does not perform a structural comparison of the contents of + // the objects. + QPDF_DLL + bool isSameObjectAs(QPDFObjectHandle const&) const; + + // Return type code and type name of underlying object. These are useful for doing rapid type + // tests (like switch statements) or for testing and debugging. + QPDF_DLL + qpdf_object_type_e getTypeCode() const; + QPDF_DLL + char const* getTypeName() const; + + // Exactly one of these will return true for any initialized object. Operator and InlineImage + // are only allowed in content streams. + QPDF_DLL + bool isBool() const; + QPDF_DLL + bool isNull() const; + QPDF_DLL + bool isInteger() const; + QPDF_DLL + bool isReal() const; + QPDF_DLL + bool isName() const; + QPDF_DLL + bool isString() const; + QPDF_DLL + bool isOperator() const; + QPDF_DLL + bool isInlineImage() const; + QPDF_DLL + bool isArray() const; + QPDF_DLL + bool isDictionary() const; + QPDF_DLL + bool isStream() const; + QPDF_DLL + bool isReserved() const; + + // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended + // for internal use, but it can be used as an efficient way to check for nulls that are not + // indirect objects. + QPDF_DLL + bool isDirectNull() const; + + // This returns true in addition to the query for the specific type for indirect objects. + QPDF_DLL + bool isIndirect() const; + + // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse + // such an object will throw a logic_error. + QPDF_DLL + bool isDestroyed() const; + + // True for everything except array, dictionary, stream, word, and inline image. + QPDF_DLL + bool isScalar() const; + + // True if the object is a name object representing the provided name. + QPDF_DLL + bool isNameAndEquals(std::string const& name) const; + + // True if the object is a dictionary of the specified type and subtype, if any. + QPDF_DLL + bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const; + + // True if the object is a stream of the specified type and subtype, if any. + QPDF_DLL + bool isStreamOfType(std::string const& type, std::string const& subtype = "") const; + + // Public factory methods + + // Wrap an object in an array if it is not already an array. This is a helper for cases in which + // something in a PDF may either be a single item or an array of items, which is a common idiom. + QPDF_DLL + QPDFObjectHandle wrapInArray(); + + // Construct an object of any type from a string representation of the object. Throws QPDFExc + // with an empty filename and an offset into the string if there is an error. Any indirect + // object syntax (obj gen R) will cause a logic_error exception to be thrown. If + // object_description is provided, it will appear in the message of any QPDFExc exception thrown + // for invalid syntax. See also the global `operator ""_qpdf` defined below. + QPDF_DLL + static QPDFObjectHandle + parse(std::string const& object_str, std::string const& object_description = ""); + + // Construct an object of any type from a string representation of the object. Indirect object + // syntax (obj gen R) is allowed and will create indirect references within the passed-in + // context. If object_description is provided, it will appear in the message of any QPDFExc + // exception thrown for invalid syntax. Note that you can't parse an indirect object reference + // all by itself as parse will stop at the end of the first complete object, which will just be + // the first number and will report that there is trailing data at the end of the string. + QPDF_DLL + static QPDFObjectHandle + parse(QPDF* context, std::string const& object_str, std::string const& object_description = ""); + + // Construct an object as above by reading from the given InputSource at its current position + // and using the tokenizer you supply. Indirect objects and encrypted strings are permitted. + // This method was intended to be called by QPDF for parsing objects that are read from the + // object's input stream. To be removed in qpdf 13. See + // . + [[deprecated("to be removed in qpdf 13")]] QPDF_DLL static QPDFObjectHandle parse( + std::shared_ptr input, + std::string const& object_description, + QPDFTokenizer&, + bool& empty, + StringDecrypter* decrypter, + QPDF* context); + + // Return the offset where the object was found when parsed. A negative value means that the + // object was created without parsing. If the object is in a stream, the offset is from the + // beginning of the stream. Otherwise, the offset is from the beginning of the file. + QPDF_DLL + qpdf_offset_t getParsedOffset() const; + + // Older method: stream_or_array should be the value of /Contents from a page object. It's more + // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error + // messages will also be more useful because the page object information will be known. + QPDF_DLL + static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks); + + // When called on a stream or stream array that is some page's content streams, do the same as + // pipePageContents. This method is a lower level way to do what + // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a + // contents object that is disconnected from a page object. The description argument should + // describe the containing page and is used in error messages. The all_description argument is + // initialized to something that could be used to describe the result of the pipeline. It is the + // description amended with the identifiers of the underlying objects. Please note that if there + // is an array of content streams, p->finish() is called after each stream. If you pass a + // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an + // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the + // end. + QPDF_DLL + void + pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description); + + // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream + // data is passed through the token filter after all original filters but before content stream + // normalization if requested. This is a low-level interface to add it to a stream. You will + // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be + // applied to a page object, and which will automatically handle the case of pages whose + // contents are split across multiple streams. + QPDF_DLL + void addTokenFilter(std::shared_ptr token_filter); + + // Legacy helpers for parsing content streams. These methods are not going away, but newer code + // should call the correspond methods in QPDFPageObjectHelper instead. The specification and + // behavior of these methods are the same as the identically named methods in that class, but + // newer functionality will be added there. + QPDF_DLL + void parsePageContents(ParserCallbacks* callbacks); + QPDF_DLL + void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr); + // See comments for QPDFPageObjectHelper::pipeContents. + QPDF_DLL + void pipePageContents(Pipeline* p); + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + // End legacy content stream helpers + + // Called on a stream to filter the stream as if it were page contents. This can be used to + // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream. + QPDF_DLL + void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr); + // Called on a stream to parse the stream as page contents. This can be used to parse a form + // XObject. + QPDF_DLL + void parseAsContents(ParserCallbacks* callbacks); + + // Type-specific factories + QPDF_DLL + static QPDFObjectHandle newNull(); + QPDF_DLL + static QPDFObjectHandle newBool(bool value); + QPDF_DLL + static QPDFObjectHandle newInteger(long long value); + QPDF_DLL + static QPDFObjectHandle newReal(std::string const& value); + QPDF_DLL + static QPDFObjectHandle + newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true); + // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes, + // excluding the NUL character, and starting with a slash. Name objects as represented in the + // PDF specification can contain characters escaped with #, but such escaping is not of concern + // when calling QPDFObjectHandle methods not directly relating to parsing. For example, + // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return + // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse() + // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and + // modifying objects, you want to work with the internal, canonical representation. For names + // containing alphanumeric characters, dashes, and underscores, there is no difference between + // the two representations. For a lengthy discussion, see + // https://github.com/qpdf/qpdf/discussions/625. + QPDF_DLL + static QPDFObjectHandle newName(std::string const& name); + QPDF_DLL + static QPDFObjectHandle newString(std::string const& str); + // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in + // PDF files outside of content streams, such as in document metadata form field values, page + // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16 + // as needed to successfully encode all the characters. + QPDF_DLL + static QPDFObjectHandle newUnicodeString(std::string const& utf8_str); + QPDF_DLL + static QPDFObjectHandle newOperator(std::string const&); + QPDF_DLL + static QPDFObjectHandle newInlineImage(std::string const&); + QPDF_DLL + static QPDFObjectHandle newArray(); + QPDF_DLL + static QPDFObjectHandle newArray(std::vector const& items); + QPDF_DLL + static QPDFObjectHandle newArray(Rectangle const&); + QPDF_DLL + static QPDFObjectHandle newArray(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newArray(QPDFMatrix const&); + QPDF_DLL + static QPDFObjectHandle newDictionary(); + QPDF_DLL + static QPDFObjectHandle newDictionary(std::map const& items); + + // Create an array from a rectangle. Equivalent to the rectangle form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromRectangle(Rectangle const&); + // Create an array from a matrix. Equivalent to the matrix form of newArray. + QPDF_DLL + static QPDFObjectHandle newFromMatrix(Matrix const&); + QPDF_DLL + static QPDFObjectHandle newFromMatrix(QPDFMatrix const&); + + // Note: new stream creation methods have were added to the QPDF class starting with + // version 11.2.0. The ones in this class are here for backward compatibility. + + // Create a new stream and associate it with the given qpdf object. A subsequent call must be + // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be + // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively, + // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can + // call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf); + + // Create a new stream and associate it with the given qpdf object. Use the given buffer as the + // stream data. The stream dictionary's /Length key will automatically be set to the size of the + // data buffer. If additional keys are required, the stream's dictionary may be retrieved by + // calling getDict(), and the resulting dictionary may be modified. This method is just a + // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience + // methods for streams that require no parameters beyond the stream length. Note that you don't + // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will + // automatically compress uncompressed stream data. Example programs are provided that + // illustrate this. From QPDF 11.2, you can call QPDF::newStream() + // instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr data); + + // Create new stream with data from string. This method will create a copy of the data rather + // than using the user-provided buffer as in the std::shared_ptr version of newStream. + // From QPDF 11.2, you can call QPDF::newStream() instead. + QPDF_DLL + static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data); + + // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is + // going to be added to the QPDF object. Normally you don't have to use this type since you can + // just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects + // with circular references, you may need to create a reserved object so that you can have a + // reference to it and then replace the object later. Reserved objects have the special + // property that they can't be resolved to direct objects. This makes it possible to replace a + // reserved object with a new object while preserving existing references to them. When you are + // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this + // purpose rather than the more general QPDF::replaceObject. It is an error to try to write a + // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call + // QPDF::newReserved() instead. + QPDF_DLL + static QPDFObjectHandle newReserved(QPDF* qpdf); + + // Provide an owning qpdf and object description. The library does this automatically with + // objects that are read from the input PDF and with objects that are created programmatically + // and inserted into the QPDF as a new indirect object. Most end user code will not need to call + // this. If an object has an owning qpdf and object description, it enables qpdf to give + // warnings with proper context in some cases where it would otherwise raise exceptions. It is + // okay to add objects without an owning_qpdf to objects that have one, but it is an error to + // have a QPDF contain objects with owning_qpdf set to something else. To add objects from + // another qpdf, use copyForeignObject instead. + QPDF_DLL + void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description); + QPDF_DLL + bool hasObjectDescription() const; + + // Accessor methods + // + // (Note: this comment is referenced in qpdf-c.h and the manual.) + // + // In PDF files, objects have specific types, but there is nothing that prevents PDF files from + // containing objects of types that aren't expected by the specification. + // + // There are two flavors of accessor methods: + // + // * getSomethingValue() returns the value and issues a type warning if the type is incorrect. + // + // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns + // true and initializes a reference of the appropriate type. These methods never issue type + // warnings. + // + // The getSomethingValue() accessors and some of the other methods expect objects of a + // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as + // trying to get a dictionary key from an array, trying to get the string value of a number, + // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using + // the following behavior: + // + // * Requesting a value of the wrong type (int value from string, array item from a scalar or + // dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for + // number, the empty string for string, or the null object for an object handle. + // + // * Accessing an array item that is out of bounds will return a null object. + // + // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to + // a scalar or array) will be ignored. + // + // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5, + // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code + // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case + // for all objects whose origin was a PDF file), the warning is issued using the normal warning + // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them. + // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created + // programmatically), an exception will be thrown. + // + // The way to avoid getting any type warnings or exceptions, even when working with malformed + // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for + // example, make sure that isString() returns true before calling getStringValue()) and to + // always be sure that any array indices are in bounds. + // + // For additional discussion and rationale for this behavior, see the section in the QPDF manual + // entitled "Object Accessor Methods". + + // Methods for bool objects + QPDF_DLL + bool getBoolValue() const; + QPDF_DLL + bool getValueAsBool(bool&) const; + + // Methods for integer objects. Note: if an integer value is too big (too far away from zero in + // either direction) to fit in the requested return type, the maximum or minimum value for that + // return type may be returned. For example, on a system with 32-bit int, a numeric object with + // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX. + QPDF_DLL + long long getIntValue() const; + QPDF_DLL + bool getValueAsInt(long long&) const; + QPDF_DLL + int getIntValueAsInt() const; + QPDF_DLL + bool getValueAsInt(int&) const; + QPDF_DLL + unsigned long long getUIntValue() const; + QPDF_DLL + bool getValueAsUInt(unsigned long long&) const; + QPDF_DLL + unsigned int getUIntValueAsUInt() const; + QPDF_DLL + bool getValueAsUInt(unsigned int&) const; + + // Methods for real objects + QPDF_DLL + std::string getRealValue() const; + QPDF_DLL + bool getValueAsReal(std::string&) const; + + // Methods that work for both integer and real objects + QPDF_DLL + bool isNumber() const; + QPDF_DLL + double getNumericValue() const; + QPDF_DLL + bool getValueAsNumber(double&) const; + + // Methods for name objects. The returned name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + std::string getName() const; + QPDF_DLL + bool getValueAsName(std::string&) const; + + // Methods for string objects + QPDF_DLL + std::string getStringValue() const; + QPDF_DLL + bool getValueAsString(std::string&) const; + + // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise, + // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to + // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters + // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range + // unmapped. + QPDF_DLL + std::string getUTF8Value() const; + QPDF_DLL + bool getValueAsUTF8(std::string&) const; + + // Methods for content stream objects + QPDF_DLL + std::string getOperatorValue() const; + QPDF_DLL + bool getValueAsOperator(std::string&) const; + QPDF_DLL + std::string getInlineImageValue() const; + QPDF_DLL + bool getValueAsInlineImage(std::string&) const; + + // Methods for array objects; see also name and array objects. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.aitems()) + // { + // // iter is an array element + // } + class QPDFArrayItems; + QPDF_DLL + QPDFArrayItems aitems(); + + QPDF_DLL + int getArrayNItems() const; + QPDF_DLL + QPDFObjectHandle getArrayItem(int n) const; + // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling + // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of + // nulls. + QPDF_DLL + std::vector getArrayAsVector() const; + QPDF_DLL + bool isRectangle() const; + // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the + // rectangle [0, 0, 0, 0] + QPDF_DLL + Rectangle getArrayAsRectangle() const; + QPDF_DLL + bool isMatrix() const; + // If the array is an array of six numeric values, return as a matrix. Otherwise, return the + // matrix [1, 0, 0, 1, 0, 0] + QPDF_DLL + Matrix getArrayAsMatrix() const; + + // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as + // canonical name strings starting with a leading slash and not containing any PDF syntax + // escaping. See comments for getName() for details. + + // Return an object that enables iteration over members. You can do + // + // for (auto iter: obj.ditems()) + // { + // // iter.first is the key + // // iter.second is the value + // } + class QPDFDictItems; + QPDF_DLL + QPDFDictItems ditems(); + + // Return true if key is present. Keys with null values are treated as if they are not present. + // This is as per the PDF spec. + QPDF_DLL + bool hasKey(std::string const&) const; + // Return the value for the key. If the key is not present, null is returned. + QPDF_DLL + QPDFObjectHandle getKey(std::string const&) const; + // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access + // lower-level dictionaries, as in + // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font"); + QPDF_DLL + QPDFObjectHandle getKeyIfDict(std::string const&) const; + // Return all keys. Keys with null values are treated as if they are not present. This is as + // per the PDF spec. + QPDF_DLL + std::set getKeys() const; + // Return dictionary as a map. Entries with null values are included. + QPDF_DLL + std::map getDictAsMap() const; + + // Methods for name and array objects. The name value is in qpdf's canonical form with all + // escaping resolved. See comments for newName() for details. + QPDF_DLL + bool isOrHasName(std::string const&) const; + + // Make all resources in a resource dictionary indirect. This just goes through all entries of + // top-level subdictionaries and converts any direct objects to indirect objects. This can be + // useful to call before mergeResources if it is going to be called multiple times to prevent + // resources from being copied multiple times. + QPDF_DLL + void makeResourcesIndirect(QPDF& owning_qpdf); + + // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in + // dictionary subitems are resolved, and "conflicts" is initialized to a map such that + // conflicts[resource_type][old_key] == [new_key] + // + // See also makeResourcesIndirect, which can be useful to call before calling this. + // + // This method does nothing if both this object and the other object are not dictionaries. + // Otherwise, it has following behavior, where "object" refers to the object whose method is + // invoked, and "other" refers to the argument: + // + // * For each key in "other" whose value is an array: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, if "object" has an array in the same place, append to that array any objects + // in "other"'s array that are not already present. + // * For each key in "other" whose value is a dictionary: + // * If "object" does not have that entry, shallow copy it. + // * Otherwise, for each key in the subdictionary: + // * If key is not present in "object"'s entry, shallow copy it if direct or just add it if + // indirect. + // * Otherwise, if conflicts are being detected: + // * If there is a key (oldkey) already in the dictionary that points to the same indirect + // destination as key, indicate that key was replaced by oldkey. This would happen if + // these two resource dictionaries have previously been merged. + // * Otherwise pick a new key (newkey) that is unique within the resource dictionary, + // store that in the resource dictionary with key's destination as its destination, and + // indicate that key was replaced by newkey. + // + // The primary purpose of this method is to facilitate merging of resource dictionaries that are + // supposed to have the same scope as each other. For example, this can be used to merge a form + // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The + // "conflicts" parameter may be previously initialized. This method adds to whatever is already + // there, which can be useful when merging with multiple things. + QPDF_DLL + void mergeResources( + QPDFObjectHandle other, + std::map>* conflicts = nullptr); + + // Get all resource names from a resource dictionary. If this object is a dictionary, this + // method returns a set of all the keys in all top-level subdictionaries. For resources + // dictionaries, this is the collection of names that may be referenced in the content stream. + QPDF_DLL + std::set getResourceNames() const; + + // Find a unique name within a resource dictionary starting with a given prefix. This method + // works by appending a number to the given prefix. It searches starting with min_suffix and + // sets min_suffix to selected value upon return. This can be used to increase efficiency if + // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next + // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling + // this multiple times on the same resource dictionary, you can initialize resource_names by + // calling getResourceNames(), incrementally update it as you add resources, and keep passing it + // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time + // it's called. + QPDF_DLL + std::string getUniqueResourceName( + std::string const& prefix, + int& min_suffix, + std::set* resource_names = nullptr) const; + + // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF + // object. Indirect objects always have an owning QPDF. Direct objects that are read from the + // input source will also have an owning QPDF. Programmatically created objects will only have + // one if setObjectDescription was called. + // + // When the QPDF object that owns an object is destroyed, the object is changed into a null, and + // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the + // life of the QPDF. If in doubt, ask for it each time you need it. + + // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it + // returns a null pointer. Use this when you are able to handle the case of an object that + // doesn't have an owning QPDF. + QPDF_DLL + QPDF* getOwningQPDF() const; + // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a + // runtime_error. Use this when you know the object has to have an owning QPDF, such as when + // it's a known indirect object. Since streams are always indirect objects, this method can be + // used safely for streams. If error_msg is specified, it will be used at the contents of the + // runtime_error if there is now owner. + QPDF_DLL + QPDF& getQPDF(std::string const& error_msg = "") const; + + // Create a shallow copy of an object as a direct object, but do not traverse across indirect + // object boundaries. That means that, for dictionaries and arrays, any keys or items that were + // indirect objects will still be indirect objects that point to the same place. In the + // strictest sense, this is not a shallow copy because it recursively descends arrays and + // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You + // can't copy a stream this way. See copyStream() instead. + QPDF_DLL + QPDFObjectHandle shallowCopy(); + + // Create a true shallow copy of an array or dictionary, just copying the immediate items + // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in + // the copy, you are modifying the original, which is almost never what you want. However, if + // your intention is merely to *replace* top-level items or keys and not to modify lower-level + // items in the copy, this method is much faster than shallowCopy(). + QPDF_DLL + QPDFObjectHandle unsafeShallowCopy(); + + // Create a copy of this stream. The new stream and the old stream are independent: after the + // copy, either the original or the copy's dictionary or data can be modified without affecting + // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's + // data are made. If the source stream's data is already being provided by a StreamDataProvider, + // the new stream will use the same one, so you have to make sure your StreamDataProvider can + // handle that case. But if you're already using a StreamDataProvider, you probably don't need + // to call this method. + QPDF_DLL + QPDFObjectHandle copyStream(); + + // Mutator methods. + + // Since qpdf 11: for mutators that may add or remove an item, there are additional versions + // whose names contain "AndGet" that return the added or removed item. For example: + // + // auto new_dict = dict.replaceKeyAndGetNew( + // "/New", QPDFObjectHandle::newDictionary()); + // + // auto old_value = dict.replaceKeyAndGetOld( + // "/New", "(something)"_qpdf); + + // Recursively copy this object, making it direct. An exception is thrown if a loop is detected. + // With allow_streams true, keep indirect object references to streams. Otherwise, throw an + // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream + // is found, the resulting object is still associated with the containing qpdf. When + // allow_streams is false, the object will no longer be connected to the original QPDF object + // after this call completes successfully. + QPDF_DLL + void makeDirect(bool allow_streams = false); + + // Mutator methods for array objects + QPDF_DLL + void setArrayItem(int, QPDFObjectHandle const&); + QPDF_DLL + void setArrayFromVector(std::vector const& items); + // Insert an item before the item at the given position ("at") so that it has that position + // after insertion. If "at" is equal to the size of the array, insert the item at the end. + QPDF_DLL + void insertItem(int at, QPDFObjectHandle const& item); + // Like insertItem but return the item that was inserted. + QPDF_DLL + QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item); + // Append an item to an array. + QPDF_DLL + void appendItem(QPDFObjectHandle const& item); + // Append an item, and return the newly added item. + QPDF_DLL + QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item); + // Remove the item at that position, reducing the size of the array by one. + QPDF_DLL + void eraseItem(int at); + // Erase and item and return the item that was removed. + QPDF_DLL + QPDFObjectHandle eraseItemAndGetOld(int at); + + // Mutator methods for dictionary objects + + // Replace value of key, adding it if it does not exist. If value is null, remove the key. + QPDF_DLL + void replaceKey(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the value. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value); + // Replace value of key and return the old value, or null if the key was previously not present. + QPDF_DLL + QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value); + // Remove key, doing nothing if key does not exist. + QPDF_DLL + void removeKey(std::string const& key); + // Remove key and return the old value. If the old value didn't exist, return a null object. + QPDF_DLL + QPDFObjectHandle removeKeyAndGetOld(std::string const& key); + + // Methods for stream objects + QPDF_DLL + QPDFObjectHandle getDict() const; + + // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode + // level, whether compression is enabled, and its ability to filter. Passing false will prevent + // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding + // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and + // recompressing a stream that it knows how to operate on for any application-specific reason, + // such as that you have already optimized its filtering. Note that this doesn't affect any + // other ways to get the stream's data, such as pipeStreamData or getStreamData. + QPDF_DLL + void setFilterOnWrite(bool); + QPDF_DLL + bool getFilterOnWrite(); + + // If addTokenFilter has been called for this stream, then the original data should be + // considered to be modified. This means we should avoid optimizations such as not filtering a + // stream that is already compressed. + QPDF_DLL + bool isDataModified(); + + // Returns filtered (uncompressed) stream data. Throws an exception if the stream is filtered + // and we can't decode it. + QPDF_DLL + std::shared_ptr getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized); + + // Returns unfiltered (raw) stream data. + QPDF_DLL + std::shared_ptr getRawStreamData(); + + // Write stream data through the given pipeline. A null pipeline value may be used if all you + // want to do is determine whether a stream is filterable and would be filtered based on the + // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags + // alter the behavior in the following way: + // + // encode_flags: + // + // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are + // applied. + // + // qpdf_sf_normalize -- tokenize as content stream and normalize tokens + // + // decode_level: + // + // qpdf_dl_none -- do not decode any streams. + // + // qpdf_dl_generalized -- decode supported general-purpose filters. This includes + // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode. + // + // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy + // specialized filters. This includes /RunLengthDecode. + // + // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported + // lossy filters. This includes /DCTDecode. + // + // If, based on the flags and the filters and decode parameters, we determine that we know how + // to apply all requested filters, do so and return true if we are successful. + // + // The exact meaning of the return value differs the different versions of this function, but + // for any version, the meaning has been the same. For the main version, added in qpdf 10, the + // return value indicates whether the overall operation succeeded. The filter parameter, if + // specified, will be set to whether or not filtering was attempted. If filtering was not + // requested, this value will be false even if the overall operation succeeded. + // + // If filtering is requested but this method returns false, it means there was some error in the + // filtering, in which case the resulting data is likely partially filtered and/or incomplete + // and may not be consistent with the configured filters. QPDFWriter handles this by attempting + // to get the stream data without filtering, but callers should consider a false return value + // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry + // in that case, pass true as the value of will_retry. This changes the warning issued by the + // library to indicate that the operation will be retried without filtering to avoid data loss. + + // Return value is overall success, even if filtering is not requested. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + bool* filtering_attempted, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy version. Return value is whether filtering was attempted. There is no way to determine + // success if filtering was not attempted. + QPDF_DLL + bool pipeStreamData( + Pipeline*, + int encode_flags, + qpdf_stream_decode_level_e decode_level, + bool suppress_warnings = false, + bool will_retry = false); + + // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows: + // filter = false -> encode_flags = 0 + // filter = true -> decode_level = qpdf_dl_generalized + // normalize = true -> encode_flags |= qpdf_sf_normalize + // compress = true -> encode_flags |= qpdf_sf_compress + // Return value is whether filtering was attempted. + QPDF_DLL + bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress); + + // Replace a stream's dictionary. The new dictionary must be consistent with the stream's data. + // This is most appropriately used when creating streams from scratch that will use a stream + // data provider and therefore start with an empty dictionary. It may be more convenient in + // this case than calling getDict and modifying it for each key. The pdf-create example does + // this. + QPDF_DLL + void replaceDict(QPDFObjectHandle const&); + + // Test whether a stream is the root XMP /Metadata object of its owning QPDF. + QPDF_DLL + bool isRootMetadata() const; + + // REPLACING STREAM DATA + + // Note about all replaceStreamData methods: whatever values are passed as filter and + // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object + // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf + // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing + // values untouched. + + // Replace this stream's stream data with the given data buffer. The stream's /Length key is + // replaced with the length of the data buffer. The stream is interpreted as if the data read + // from the file, after any decryption filters have been applied, is as presented. + QPDF_DLL + void replaceStreamData( + std::shared_ptr data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Replace the stream's stream data with the given string. This method will create a copy of the + // data rather than using the user-provided buffer as in the std::shared_ptr version of + // replaceStreamData. + QPDF_DLL + void replaceStreamData( + std::string const& data, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // As above, replace this stream's stream data. Instead of directly providing a buffer with the + // stream data, call the given provider's provideStreamData method. See comments on the + // StreamDataProvider class (defined above) for details on the method. The data must be + // consistent with filter and decode_parms as provided. Although it is more complex to use this + // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid + // allocating memory for the stream data. Example programs are provided that use both forms of + // replaceStreamData. + + // Note about stream length: for any given stream, the provider must provide the same amount of + // data each time it is called. This is critical for making linearization work properly. + // Versions of qpdf before 3.0.0 required a length to be specified here. Starting with + // version 3.0.0, this is no longer necessary (or permitted). The first time the stream data + // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is + // enforced that the length be the same as the first time. + + // If you have gotten a compile error here while building code that worked with older versions + // of qpdf, just omit the length parameter. You can also simplify your code by not having to + // compute the length in advance. + QPDF_DLL + void replaceStreamData( + std::shared_ptr provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider. + + // The provider should write the stream data to the pipeline. For a one-liner to replace stream + // data with the contents of a file, pass QUtil::file_provider(filename) as provider. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + // The provider should write the stream data to the pipeline, returning true if it succeeded + // without errors. + QPDF_DLL + void replaceStreamData( + std::function provider, + QPDFObjectHandle const& filter, + QPDFObjectHandle const& decode_parms); + + // Access object ID and generation. For direct objects, return object ID 0. + + // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to + // the pattern of depending on object ID or generation without the other. In general, when + // keeping track of object IDs, it's better to use QPDFObjGen instead. + + QPDF_DLL + QPDFObjGen getObjGen() const; + QPDF_DLL + int getObjectID() const; + QPDF_DLL + int getGeneration() const; + + QPDF_DLL + std::string unparse() const; + QPDF_DLL + std::string unparseResolved() const; + // For strings only, force binary representation. Otherwise, same as unparse. + QPDF_DLL + std::string unparseBinary() const; + + // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available + // JSON version. The JSON is generated as follows: + // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their + // native JSON types. + // * Names are encoded as strings representing the canonical representation (after parsing #xx) + // and preceded by a slash, just as unparse() returns. For example, the JSON for the + // PDF-syntax name /Text#2fPlain would be "/Text/Plain". + // * Indirect references are encoded as strings containing "obj gen R" + // * Strings + // * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters + // encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode + // mappings are not reversible. There is no way to tell the difference between a string that + // looks like a name or indirect object from an actual name or indirect object. + // * JSON v2: + // * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally + // mapped to Unicode (which is all strings without undefined characters) are represented + // as "u:" followed by the UTF-8 encoded string. Example: + // "u:potato". + // * All other strings are represented as "b:" followed by a hexadecimal encoding of the + // string. Example: "b:0102cacb" + // * Streams + // * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a + // dictionary other than context. + // * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the + // stream's dictionary. Since "dict" does not otherwise represent anything, this is + // unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data. + // * Object types that are only valid in content streams (inline image, operator) are serialized + // as "null". Attempting to serialize a "reserved" object is an error. + // If dereference_indirect is true and this is an indirect object, show the actual contents of + // the object. The effect of dereference_indirect applies only to this object. It is not + // recursive. + QPDF_DLL + JSON getJSON(int json_version, bool dereference_indirect = false) const; + + // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient + // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the + // documentation for getJSON and JSON::write for further detail. + QPDF_DLL + void writeJSON( + int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const; + + // This method can be called on a stream to get a more extended JSON representation of the + // stream that includes the stream's data. The JSON object returned is always a dictionary whose + // "dict" key is an encoding of the stream's dictionary. The representation of the data is + // determined by the json_data field. + // + // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file. + // + // If json_data is qpdf_sj_none, stream data is not represented. + // + // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on + // the value of decode_level, which has the same meaning as with pipeStreamData. + // + // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data" + // field of the dictionary that is returned. + // + // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be + // supplied. The value of data_filename is stored in the resulting json in the "datafile" key + // but is not otherwise use. The stream data itself (raw or filtered depending on decode level), + // is written to the pipeline via pipeStreamData(). + // + // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must + // remain valid until after the JSON object is written. + QPDF_DLL + JSON getStreamJSON( + int json_version, + qpdf_json_stream_data_e json_data, + qpdf_stream_decode_level_e decode_level, + Pipeline* p, + std::string const& data_filename); + + // Legacy helper methods for commonly performed operations on pages. Newer code should use + // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as + // the identically named methods in that class, but newer functionality will be added there. + QPDF_DLL + std::map getPageImages(); + QPDF_DLL + std::vector getPageContents(); + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + QPDF_DLL + void rotatePage(int angle, bool relative); + QPDF_DLL + void coalesceContentStreams(); + // End legacy page helpers + + // Issue a warning about this object if possible. If the object has a description, a warning + // will be issued using the owning QPDF as context. Otherwise, a message will be written to the + // default logger's error stream, which is standard error if not overridden. Objects read + // normally from the file have descriptions. See comments on setObjectDescription for additional + // details. + QPDF_DLL + void warnIfPossible(std::string const& warning) const; + + // Convenience routine: Throws if the assumption is violated. Your code will be better if you + // call one of the isType methods and handle the case of the type being wrong, but these can be + // convenient if you have already verified the type. + QPDF_DLL + void assertInitialized() const; + + QPDF_DLL + void assertNull() const; + QPDF_DLL + void assertBool() const; + QPDF_DLL + void assertInteger() const; + QPDF_DLL + void assertReal() const; + QPDF_DLL + void assertName() const; + QPDF_DLL + void assertString() const; + QPDF_DLL + void assertOperator() const; + QPDF_DLL + void assertInlineImage() const; + QPDF_DLL + void assertArray() const; + QPDF_DLL + void assertDictionary() const; + QPDF_DLL + void assertStream() const; + QPDF_DLL + void assertReserved() const; + + QPDF_DLL + void assertIndirect() const; + QPDF_DLL + void assertScalar() const; + QPDF_DLL + void assertNumber() const; + + // The isPageObject method checks the /Type key of the object. This is not completely reliable + // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is + // slightly more accepting but may still return false here when treating the object as a page + // would work. Use this sparingly. + QPDF_DLL + bool isPageObject() const; + QPDF_DLL + bool isPagesObject() const; + QPDF_DLL + void assertPageObject() const; + + QPDF_DLL + bool isFormXObject() const; + + // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as + // images. + QPDF_DLL + bool isImage(bool exclude_imagemask = true) const; + + // The following methods do not form part of the public API and are for internal use only. + + QPDFObjectHandle(std::shared_ptr const& obj) : + qpdf::BaseHandle(obj) + { + } + QPDFObjectHandle(std::shared_ptr&& obj) : + qpdf::BaseHandle(std::move(obj)) + { + } + std::shared_ptr + getObj() + { + return obj; + } + + void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const; + + inline qpdf::Array as_array(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Dictionary as_dictionary(qpdf::typed options = qpdf::typed::any) const; + inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const; + + private: + void typeWarning(char const* expected_type, std::string const& warning) const; + void objectWarning(std::string const& warning) const; + void assertType(char const* type_name, bool istype) const; + void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); + void setParsedOffset(qpdf_offset_t offset); + void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); + static void parseContentStream_data( + std::string_view stream_data, + std::string const& description, + ParserCallbacks* callbacks, + QPDF* context); + std::vector + arrayOrStreamToStreamArray(std::string const& description, std::string& all_description); + void checkOwnership(QPDFObjectHandle const&) const; +}; + +#ifndef QPDF_NO_QPDF_STRING +// This is short for QPDFObjectHandle::parse, so you can do + +// auto oh = "<< /Key (value) >>"_qpdf; + +// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration +// from being here. + +/* clang-format off */ + // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest + // of the file as a string if clang-format removes the space after "operator", and as of + // clang-format 15, there's no way to prevent it from doing so. + QPDF_DLL + QPDFObjectHandle operator ""_qpdf(char const* v, size_t len); +/* clang-format on */ + +#endif // QPDF_NO_QPDF_STRING + +class QPDFObjectHandle::QPDFDictItems +{ + // This class allows C++-style iteration, including range-for iteration, around dictionaries. + // You can write + + // for (auto iter: QPDFDictItems(dictionary_obj)) + // { + // // iter.first is a string + // // iter.second is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFDictItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFDictItems; + + public: + typedef std::pair T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFDictItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + std::set keys; + std::set::iterator iter; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +class QPDFObjectHandle::QPDFArrayItems +{ + // This class allows C++-style iteration, including range-for iteration, around arrays. You can + // write + + // for (auto iter: QPDFArrayItems(array_obj)) + // { + // // iter is a QPDFObjectHandle + // } + + // See examples/pdf-name-number-tree.cc for a demonstration of using this API. + + public: + QPDF_DLL + QPDFArrayItems(QPDFObjectHandle const& oh); + + class iterator + { + friend class QPDFArrayItems; + + public: + typedef QPDFObjectHandle T; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = T; + using difference_type = long; + using pointer = T*; + using reference = T&; + + virtual ~iterator() = default; + QPDF_DLL + iterator& operator++(); + iterator + operator++(int) + { + iterator t = *this; + ++(*this); + return t; + } + QPDF_DLL + iterator& operator--(); + iterator + operator--(int) + { + iterator t = *this; + --(*this); + return t; + } + QPDF_DLL + reference operator*(); + QPDF_DLL + pointer operator->(); + QPDF_DLL + bool operator==(iterator const& other) const; + bool + operator!=(iterator const& other) const + { + return !operator==(other); + } + + private: + iterator(QPDFObjectHandle& oh, bool for_begin); + void updateIValue(); + + class Members + { + friend class QPDFArrayItems::iterator; + + public: + ~Members() = default; + + private: + Members(QPDFObjectHandle& oh, bool for_begin); + Members() = delete; + Members(Members const&) = delete; + + QPDFObjectHandle& oh; + int item_number; + bool is_end; + }; + std::shared_ptr m; + value_type ivalue; + }; + + QPDF_DLL + iterator begin(); + QPDF_DLL + iterator end(); + + private: + QPDFObjectHandle oh; +}; + +namespace qpdf +{ + inline BaseHandle:: + operator bool() const + { + return static_cast(obj); + } + + inline BaseHandle:: + operator QPDFObjectHandle() const + { + return {obj}; + } + +} // namespace qpdf + +inline bool +QPDFObjectHandle::isInitialized() const +{ + return obj != nullptr; +} + +#endif // QPDFOBJECTHANDLE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjectHelper.hh new file mode 100644 index 0000000..d19ba3b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFObjectHelper.hh @@ -0,0 +1,70 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOBJECTHELPER_HH +#define QPDFOBJECTHELPER_HH + +#include + +#include + +// This is a base class for QPDF Object Helper classes. Object helpers are classes that provide a +// convenient, higher-level API for working with specific types of QPDF objects. Object helpers are +// always initialized with a QPDFObjectHandle, and the underlying object handle can always be +// retrieved. The intention is that you may freely intermix use of object helpers with the +// underlying QPDF objects unless there is a specific comment in a specific helper method that says +// otherwise. The pattern of using helper objects was introduced to allow creation of higher level +// helper functions without polluting the public interface of QPDFObjectHandle. +class QPDF_DLL_CLASS QPDFObjectHelper: public qpdf::BaseHandle +{ + public: + QPDFObjectHelper(QPDFObjectHandle oh) : + qpdf::BaseHandle(oh.getObj()) + { + } + QPDF_DLL + virtual ~QPDFObjectHelper(); + QPDFObjectHandle + getObjectHandle() + { + return {obj}; + } + QPDFObjectHandle const + getObjectHandle() const + { + return {obj}; + } + + protected: + QPDF_DLL_PRIVATE + QPDFObjectHandle + oh() + { + return {obj}; + } + QPDF_DLL_PRIVATE + QPDFObjectHandle const + oh() const + { + return {obj}; + } + QPDFObjectHandle oh_; +}; + +#endif // QPDFOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFOutlineDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFOutlineDocumentHelper.hh new file mode 100644 index 0000000..66b4481 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFOutlineDocumentHelper.hh @@ -0,0 +1,92 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEDOCUMENTHELPER_HH +#define QPDFOUTLINEDOCUMENTHELPER_HH + +#include +#include +#include +#include +#include + +#include +#include + +#include + +// This is a document helper for outlines, also known as bookmarks. Outlines are discussed in +// section 12.3.3 of the PDF spec (ISO-32000). With the help of QPDFOutlineObjectHelper, the +// outlines tree is traversed, and a bidirectional map is made between pages and outlines. See also +// QPDFOutlineObjectHelper. +class QPDFOutlineDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFOutlineDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Outlines structure. This is useful if you have modified the structure of the + // Outlines dictionary in a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFOutlineDocumentHelper(QPDF&); + + ~QPDFOutlineDocumentHelper() override = default; + + QPDF_DLL + bool hasOutlines(); + + QPDF_DLL + std::vector getTopLevelOutlines(); + + // If the name is a name object, look it up in the /Dests key of the document catalog. If the + // name is a string, look it up in the name tree pointed to by the /Dests key of the names + // dictionary. + QPDF_DLL + QPDFObjectHandle resolveNamedDest(QPDFObjectHandle name); + + // Return a list outlines that are known to target the specified page. + QPDF_DLL + std::vector getOutlinesForPage(QPDFObjGen); + + class Accessor + { + friend class QPDFOutlineObjectHelper; + + static bool checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen og); + }; + + private: + void initializeByPage(); + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFOutlineObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFOutlineObjectHelper.hh new file mode 100644 index 0000000..108ec59 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFOutlineObjectHelper.hh @@ -0,0 +1,109 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFOUTLINEOBJECTHELPER_HH +#define QPDFOUTLINEOBJECTHELPER_HH + +#include +#include +#include + +class QPDFOutlineDocumentHelper; + +#include + +// This is an object helper for outline items. Outlines, also known as bookmarks, are described in +// section 12.3.3 of the PDF spec (ISO-32000). See comments below for details. +class QPDFOutlineObjectHelper: public QPDFObjectHelper +{ + public: + ~QPDFOutlineObjectHelper() override + { + // This must be cleared explicitly to avoid circular references that prevent cleanup of + // shared pointers. + m->parent = nullptr; + } + + // All constructors are private. You can only create one of these using + // QPDFOutlineDocumentHelper. + + // Return parent pointer. Returns a null pointer if this is a top-level outline. + QPDF_DLL + std::shared_ptr getParent(); + + // Return children as a list. + QPDF_DLL + std::vector getKids(); + + // Return the destination, regardless of whether it is named or explicit and whether it is + // directly provided or in a GoTo action. Returns a null object if the destination can't be + // determined. Named destinations can be resolved using the older root /Dest dictionary or the + // current names tree. + QPDF_DLL + QPDFObjectHandle getDest(); + + // Return the page that the outline points to. Returns a null object if the destination page + // can't be determined. + QPDF_DLL + QPDFObjectHandle getDestPage(); + + // Returns the value of /Count as present in the object, or 0 if not present. If count is + // positive, the outline is open. If negative, it is closed. Either way, the absolute value is + // the number of descendant items that would be visible if this were open. + QPDF_DLL + int getCount(); + + // Returns the title as a UTF-8 string. Returns an empty string if there is no title. + QPDF_DLL + std::string getTitle(); + + class Accessor + { + friend class QPDFOutlineDocumentHelper; + + static QPDFOutlineObjectHelper + create(QPDFObjectHandle oh, QPDFOutlineDocumentHelper& dh, int depth) + { + return {oh, dh, depth}; + } + }; + + private: + QPDFOutlineObjectHelper(QPDFObjectHandle, QPDFOutlineDocumentHelper&, int); + + class Members + { + friend class QPDFOutlineObjectHelper; + + public: + ~Members() = default; + + private: + Members(QPDFOutlineDocumentHelper& dh); + Members(Members const&) = delete; + + QPDFOutlineDocumentHelper& dh; + std::shared_ptr parent; + std::vector kids; + }; + + std::shared_ptr m; +}; + +#endif // QPDFOUTLINEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageDocumentHelper.hh new file mode 100644 index 0000000..a2cd9f8 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageDocumentHelper.hh @@ -0,0 +1,128 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEDOCUMENTHELPER_HH +#define QPDFPAGEDOCUMENTHELPER_HH + +#include +#include +#include + +#include + +#include + +#include + +class QPDFAcroFormDocumentHelper; + +class QPDFPageDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the Acroform structure, which can be expensive. + QPDF_DLL + static QPDFPageDocumentHelper& get(QPDF& qpdf); + + // Re-validate the Pages structure. This is useful if you have modified the Pages structure in + // a way that would invalidate the cache. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageDocumentHelper(QPDF&); + + ~QPDFPageDocumentHelper() override = default; + + // Traverse page tree, and return all /Page objects wrapped in QPDFPageObjectHelper objects. + // Unlike with QPDF::getAllPages, the vector of pages returned by this call is not affected by + // additions or removals of pages. If you manipulate pages, you will have to call this again to + // get a new copy. Please see comments in QPDF.hh for getAllPages() for additional details. + QPDF_DLL + std::vector getAllPages(); + + // The PDF /Pages tree allows inherited values. Working with the pages of a pdf is much easier + // when the inheritance is resolved by explicitly setting the values in each /Page. + QPDF_DLL + void pushInheritedAttributesToPage(); + + // This calls QPDFPageObjectHelper::removeUnreferencedResources for every page in the document. + // See comments in QPDFPageObjectHelper.hh for details. + QPDF_DLL + void removeUnreferencedResources(); + + // Add a new page at the beginning or the end of the current pdf. The newpage parameter may be + // either a direct object, an indirect object from this QPDF, or an indirect object from another + // QPDF. If it is a direct object, it will be made indirect. If it is an indirect object from + // another QPDF, this method will call pushInheritedAttributesToPage on the other file and then + // copy the page to this QPDF using the same underlying code as copyForeignObject. At this + // stage, if the indirect object is already in the pages tree, a shallow copy is made to avoid + // adding the same page more than once. In version 10.3.1 and earlier, adding a page that + // already existed would throw an exception and could cause qpdf to crash on subsequent page + // insertions in some cases. Note that this means that, in some cases, the page actually added + // won't be exactly the same object as the one passed in. If you want to do subsequent + // modification on the page, you should retrieve it again. + // + // Note that you can call copyForeignObject directly to copy a page from a different file, but + // the resulting object will not be a page in the new file. You could do this, for example, to + // convert a page into a form XObject, though for that, you're better off using + // QPDFPageObjectHelper::getFormXObjectForPage. + // + // This method does not have any specific awareness of annotations or form fields, so if you + // just add a page without thinking about it, you might end up with two pages that share form + // fields or annotations. While the page may look fine, it will probably not function properly + // with regard to interactive features. To work around this, you should call + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations. A future version of qpdf will likely + // provide a higher-level interface for copying pages around that will handle document-level + // constructs in a less error-prone fashion. + + QPDF_DLL + void addPage(QPDFPageObjectHelper newpage, bool first); + + // Add new page before or after refpage. See comments for addPage for details about what newpage + // should be. + QPDF_DLL + void addPageAt(QPDFPageObjectHelper newpage, bool before, QPDFPageObjectHelper refpage); + + // Remove page from the pdf. + QPDF_DLL + void removePage(QPDFPageObjectHelper page); + + // For every annotation, integrate the annotation's appearance stream into the containing page's + // content streams, merge the annotation's resources with the page's resources, and remove the + // annotation from the page. Handles widget annotations associated with interactive form fields + // as a special case, including removing the /AcroForm key from the document catalog. The values + // passed to required_flags and forbidden_flags are passed along to + // QPDFAnnotationObjectHelper::getPageContentForAppearance. See comments there in + // QPDFAnnotationObjectHelper.hh for meanings of those flags. + QPDF_DLL + void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageLabelDocumentHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageLabelDocumentHelper.hh new file mode 100644 index 0000000..51e2265 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageLabelDocumentHelper.hh @@ -0,0 +1,99 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGELABELDOCUMENTHELPER_HH +#define QPDFPAGELABELDOCUMENTHELPER_HH + +#include + +#include +#include + +#include + +// Page labels are discussed in the PDF spec (ISO-32000) in section 12.4.2. +// +// Page labels are implemented as a number tree. Each key is a page index, numbered from 0. The +// values are dictionaries with the following keys, all optional: +// +// * /Type: if present, must be /PageLabel +// * /S: one of /D, /R, /r, /A, or /a for decimal, upper-case and lower-case Roman numeral, or +// upper-case and lower-case alphabetic +// * /P: if present, a fixed prefix string that is prepended to each page number +// * /St: the starting number, or 1 if not specified + +class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper +{ + public: + // Get a shared document helper for a given QPDF object. + // + // Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated + // validation of the PageLabels structure, which can be expensive. + QPDF_DLL + static QPDFPageLabelDocumentHelper& get(QPDF& qpdf); + + // Re-validate the PageLabels structure. This is useful if you have modified the structure of + // the PageLabels dictionary in a way that could have invalidated the structure. + // + // If repair is true, the document will be repaired if possible if the validation encounters + // errors. + QPDF_DLL + void validate(bool repair = true); + + QPDF_DLL + QPDFPageLabelDocumentHelper(QPDF&); + + ~QPDFPageLabelDocumentHelper() override = default; + + QPDF_DLL + bool hasPageLabels(); + + // Helper function to create a dictionary suitable for adding to the /PageLabels numbers tree. + QPDF_DLL + static QPDFObjectHandle + pageLabelDict(qpdf_page_label_e label_type, int start_num, std::string_view prefix); + + // Return a page label dictionary representing the page label for the given page. The page does + // not need to appear explicitly in the page label dictionary. This method will adjust /St as + // needed to produce a label that is suitable for the page. + QPDF_DLL + QPDFObjectHandle getLabelForPage(long long page_idx); + + // Append to the incoming vector a list of objects suitable for inclusion in a /PageLabels + // dictionary's /Nums field. start_idx and end_idx are the indexes to the starting and ending + // pages (inclusive) in the original file, and new_start_idx is the index to the first page in + // the new file. For example, if pages 10 through 12 of one file are being copied to a new file + // as pages 6 through 8, you would call getLabelsForPageRange(10, 12, 6), which would return as + // many entries as are required to add to the new file's PageLabels. This method fabricates a + // suitable entry even if the original document has no page labels. This behavior facilitates + // using this function to incrementally build up a page labels tree when merging files. + QPDF_DLL + void getLabelsForPageRange( + long long start_idx, + long long end_idx, + long long new_start_idx, + std::vector& new_labels); + + private: + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFPAGELABELDOCUMENTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageObjectHelper.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageObjectHelper.hh new file mode 100644 index 0000000..ef8346e --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFPageObjectHelper.hh @@ -0,0 +1,423 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFPAGEOBJECTHELPER_HH +#define QPDFPAGEOBJECTHELPER_HH + +#include +#include +#include + +#include + +#include +#include + +class QPDFAcroFormDocumentHelper; + +// This is a helper class for page objects, but as of qpdf 10.1, many of the methods also work +// for form XObjects. When this is the case, it is noted in the comment. +class QPDFPageObjectHelper: public QPDFObjectHelper +{ + public: + QPDF_DLL + QPDFPageObjectHelper(QPDFObjectHandle); + + ~QPDFPageObjectHelper() override = default; + + // PAGE ATTRIBUTES + + // The getAttribute method works with pages and form XObjects. It returns the value of the + // requested attribute from the page/form XObject's dictionary, taking inheritance from the + // pages tree into consideration. For pages, the attributes /MediaBox, /CropBox, /Resources, and + // /Rotate are inheritable, meaning that if they are not present directly on the page node, they + // may be inherited from ancestor nodes in the pages tree. + // + // There are two ways that an attribute can be "shared": + // + // * For inheritable attributes on pages, it may appear in a higher level node of the pages tree + // + // * For any attribute, the attribute may be an indirect object which may be referenced by more + // than one page/form XObject. + // + // If copy_if_shared is true, then this method will replace the attribute with a shallow copy if + // it is indirect or inherited and return the copy. You should do this if you are going to + // modify the returned object and want the modifications to apply to the current page/form + // XObject only. + QPDF_DLL + QPDFObjectHandle getAttribute(std::string const& name, bool copy_if_shared); + + // PAGE BOXES + // + // Pages have various types of boundary boxes. These are described in detail in the PDF + // specification (section 14.11.2 Page boundaries). They are, by key in the page dictionary: + // + // * /MediaBox -- boundaries of physical page + // * /CropBox -- clipping region of what is displayed + // * /BleedBox -- clipping region for production environments + // * /TrimBox -- dimensions of final printed page after trimming + // * /ArtBox -- extent of meaningful content including margins + // + // Of these, only /MediaBox is required. If any are absent, the + // fallback value for /CropBox is /MediaBox, and the fallback + // values for the other boxes are /CropBox. + // + // As noted above (PAGE ATTRIBUTES), /MediaBox and /CropBox can be inherited from parent nodes + // in the pages tree. The other boxes can't be inherited. + // + // When the comments below refer to the "effective value" of a box, this takes into + // consideration both inheritance through the pages tree (in the case of /MediaBox and /CropBox) + // and fallback values for missing attributes (for all except /MediaBox). + // + // For the methods below, copy_if_shared is passed to getAttribute and therefore refers only to + // indirect objects and values that are inherited through the pages tree. + // + // If copy_if_fallback is true, a copy is made if the object's value was obtained by falling + // back to a different box. + // + // The copy_if_shared and copy_if_fallback parameters carry across multiple layers. This is + // explained below. + // + // You should set copy_if_shared to true if you want to modify a bounding box for the current + // page without affecting other pages but you don't want to change the fallback behavior. For + // example, if you want to modify the /TrimBox for the current page only but have it continue to + // fall back to the value of /CropBox or /MediaBox if they are not defined, you could set + // copy_if_shared to true. + // + // You should set copy_if_fallback to true if you want to modify a specific box as distinct from + // any other box. For example, if you want to make /TrimBox differ from /CropBox, then you + // should set copy_if_fallback to true. + // + // The copy_if_fallback flags were added in qpdf 11. + // + // For example, suppose that neither /CropBox nor /TrimBox is present on a page but /CropBox is + // present in the page's parent node in the page tree. + // + // * getTrimBox(false, false) would return the /CropBox from the parent node. + // + // * getTrimBox(true, false) would make a shallow copy of the /CropBox from the parent node into + // the current node and return it. + // + // * getTrimBox(false, true) would make a shallow copy of the /CropBox from the parent node into + // /TrimBox of the current node and return it. + // + // * getTrimBox(true, true) would make a shallow copy of the /CropBox from the parent node into + // the current node, then make a shallow copy of the resulting copy to /TrimBox of the current + // node, and then return that. + // + // To illustrate how these parameters carry across multiple layers, suppose that neither + // /MediaBox, /CropBox, nor /TrimBox is present on a page but /MediaBox is present on the + // parent. In this case: + // + // * getTrimBox(false, false) would return the value of /MediaBox from the parent node. + // + // * getTrimBox(true, false) would copy /MediaBox to the current node and return it. + // + // * getTrimBox(false, true) would first copy /MediaBox from the parent to /CropBox, then copy + // /CropBox to /TrimBox, and then return the result. + // + // * getTrimBox(true, true) would first copy /MediaBox from the parent to the current page, then + // copy it to /CropBox, then copy /CropBox to /TrimBox, and then return the result. + // + // If you need different behavior, call getAttribute directly and take care of your own copying. + + // Return the effective MediaBox + QPDF_DLL + QPDFObjectHandle getMediaBox(bool copy_if_shared = false); + + // Return the effective CropBox. If not defined, fall back to MediaBox + QPDF_DLL + QPDFObjectHandle getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective BleedBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective TrimBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Return the effective ArtBox. If not defined, fall back to CropBox. + QPDF_DLL + QPDFObjectHandle getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false); + + // Iterate through XObjects, possibly recursing into form XObjects. This works with pages or + // form XObjects. Call action on each XObject for which selector, if specified, returns true. + // With no selector, calls action for every object. In addition to the object being passed to + // action, the containing XObject dictionary and key are passed in. Remember that the XObject + // dictionary may be shared, and the object may appear in multiple XObject dictionaries. + QPDF_DLL + void forEachXObject( + bool recursive, + std::function action, + std::function selector = nullptr); + // Only call action for images + QPDF_DLL + void forEachImage( + bool recursive, + std::function action); + // Only call action for form XObjects + QPDF_DLL + void forEachFormXObject( + bool recursive, + std::function action); + + // Returns an empty map if there are no images or no resources. Prior to qpdf 8.4.0, this + // function did not support inherited resources, but it does now. Return value is a map from + // XObject name to the image object, which is always a stream. Works with form XObjects as well + // as pages. This method does not recurse into nested form XObjects. For that, use forEachImage. + QPDF_DLL + std::map getImages(); + + // Old name -- calls getImages() + QPDF_DLL + std::map getPageImages(); + + // Returns an empty map if there are no form XObjects or no resources. Otherwise, returns a map + // of keys to form XObjects directly referenced from this page or form XObjects. This does not + // recurse into nested form XObjects. For that, use forEachFormXObject. + QPDF_DLL + std::map getFormXObjects(); + + // Converts each inline image to an external (normal) image if the size is at least the + // specified number of bytes. This method works with pages or form XObjects. By default, it + // recursively processes nested form XObjects. Pass true as shallow to avoid this behavior. + // Prior to qpdf 10.1, form XObjects were ignored, but this was considered a bug. + QPDF_DLL + void externalizeInlineImages(size_t min_size = 0, bool shallow = false); + + // Return the annotations in the page's "/Annots" list, if any. If only_subtype is non-empty, + // only include annotations of the given subtype. + QPDF_DLL + std::vector getAnnotations(std::string const& only_subtype = ""); + + // Returns a vector of stream objects representing the content streams for the given page. This + // routine allows the caller to not care whether there are one or more than one content streams + // for a page. + QPDF_DLL + std::vector getPageContents(); + + // Add the given object as a new content stream for this page. If parameter 'first' is true, add + // to the beginning. Otherwise, add to the end. This routine automatically converts the page + // contents to an array if it is a scalar, allowing the caller not to care what the initial + // structure is. You can call coalesceContentStreams() afterwards if you want to force it to be + // a single stream. + QPDF_DLL + void addPageContents(QPDFObjectHandle contents, bool first); + + // Rotate a page. If relative is false, set the rotation of the page to angle. Otherwise, add + // angle to the rotation of the page. Angle must be a multiple of 90. Adding 90 to the rotation + // rotates clockwise by 90 degrees. + QPDF_DLL + void rotatePage(int angle, bool relative); + + // Coalesce a page's content streams. A page's content may be a stream or an array of streams. + // If this page's content is an array, concatenate the streams into a single stream. This can be + // useful when working with files that split content streams in arbitrary spots, such as in the + // middle of a token, as that can confuse some software. You could also call this after calling + // addPageContents. + QPDF_DLL + void coalesceContentStreams(); + + // + // Content stream handling + // + + // Parse a page's contents through ParserCallbacks, described above. This method works whether + // the contents are a single stream or an array of streams. Call on a page object. Also works + // for form XObjects. + QPDF_DLL + void parseContents(QPDFObjectHandle::ParserCallbacks* callbacks); + // Old name + QPDF_DLL + void parsePageContents(QPDFObjectHandle::ParserCallbacks* callbacks); + + // Pass a page's or form XObject's contents through the given TokenFilter. If a pipeline is also + // provided, it will be the target of the write methods from the token filter. If a pipeline is + // not specified, any output generated by the token filter will be discarded. Use this interface + // if you need to pass a page's contents through filter for work purposes without having that + // filter automatically applied to the page's contents, as happens with addContentTokenFilter. + // See examples/pdf-count-strings.cc for an example. + QPDF_DLL + void filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Old name -- calls filterContents() + QPDF_DLL + void filterPageContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr); + + // Pipe a page's contents through the given pipeline. This method works whether the contents are + // a single stream or an array of streams. Also works on form XObjects. + QPDF_DLL + void pipeContents(Pipeline* p); + // Old name + QPDF_DLL + void pipePageContents(Pipeline* p); + + // Attach a token filter to a page's contents. If the page's contents is an array of streams, it + // is automatically coalesced. The token filter is applied to the page's contents as a single + // stream. Also works on form XObjects. + QPDF_DLL + void addContentTokenFilter(std::shared_ptr token_filter); + + // A page's resources dictionary maps names to objects elsewhere in the file. This method walks + // through a page's contents and keeps tracks of which resources are referenced somewhere in the + // contents. Then it removes from the resources dictionary any object that is not referenced in + // the contents. This operation is most useful after calling + // QPDFPageDocumentHelper::pushInheritedAttributesToPage(). This method is used by page + // splitting code to avoid copying unused objects in files that used shared resource + // dictionaries across multiple pages. This method recurses into form XObjects and can be called + // with a form XObject as well as a page. + QPDF_DLL + void removeUnreferencedResources(); + + // Return a new QPDFPageObjectHelper that is a duplicate of the page. The returned object is an + // indirect object that is ready to be inserted into the same or a different QPDF object using + // any of the addPage methods in QPDFPageDocumentHelper or QPDF. Without calling one of those + // methods, the page will not be added anywhere. The new page object shares all content streams + // and indirect object resources with the original page, so if you are going to modify the + // contents or other aspects of the page, you will need to handling copying of the component + // parts separately. + QPDF_DLL + QPDFPageObjectHelper shallowCopyPage(); + + // Return a transformation matrix whose effect is the same as the page's /Rotate and /UserUnit + // parameters. If invert is true, return a matrix whose effect is the opposite. The regular + // matrix is suitable for taking something from this page to put elsewhere, and the second one + // is suitable for putting something else onto this page. The page's TrimBox is used as the + // bounding box for purposes of computing the matrix. + QPDF_DLL + QPDFObjectHandle::Matrix getMatrixForTransformations(bool invert = false); + + // Return a form XObject that draws this page. This is useful for n-up operations, underlay, + // overlay, thumbnail generation, or any other case in which it is useful to replicate the + // contents of a page in some other context. The dictionaries are shallow copies of the original + // page dictionary, and the contents are coalesced from the page's contents. The resulting + // object handle is not referenced anywhere. If handle_transformations is true, the resulting + // form XObject's /Matrix will be set to replicate rotation (/Rotate) and scaling (/UserUnit) in + // the page's dictionary. In this way, the page's transformations will be preserved when placing + // this object on another page. + QPDF_DLL + QPDFObjectHandle getFormXObjectForPage(bool handle_transformations = true); + + // Return content stream text that will place the given form XObject (fo) using the resource + // name "name" on this page centered within the given rectangle. If invert_transformations is + // true, the effect of any rotation (/Rotate) and scaling (/UserUnit) applied to the current + // page will be inverted in the form XObject placement. This will cause the form XObject's + // absolute orientation to be preserved. You could overlay one page on another by calling + // getFormXObjectForPage on the original page, QPDFObjectHandle::getUniqueResourceName on the + // destination page's Resources dictionary to generate a name for the resulting object, and + // calling placeFormXObject on the destination page. Then insert the new fo (or, if it comes + // from a different file, the result of calling copyForeignObject on it) into the resources + // dictionary using name, and append or prepend the content to the page's content streams. See + // the overlay/underlay code in qpdf.cc or examples/pdf-overlay-page.cc for an example. From + // qpdf 10.0.0, the allow_shrink and allow_expand parameters control whether the form XObject is + // allowed to be shrunk or expanded to stay within or maximally fill the destination rectangle. + // The default values are for backward compatibility with the pre-10.0.0 behavior. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Alternative version that also fills in the transformation matrix that was used. + QPDF_DLL + std::string placeFormXObject( + QPDFObjectHandle fo, + std::string const& name, + QPDFObjectHandle::Rectangle rect, + QPDFMatrix& cm, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // Return the transformation matrix that translates from the given form XObject's coordinate + // system into the given rectangular region on the page. The parameters have the same meaning as + // for placeFormXObject. + QPDF_DLL + QPDFMatrix getMatrixForFormXObjectPlacement( + QPDFObjectHandle fo, + QPDFObjectHandle::Rectangle rect, + bool invert_transformations = true, + bool allow_shrink = true, + bool allow_expand = false); + + // If a page is rotated using /Rotate in the page's dictionary, instead rotate the page by the + // same amount by altering the contents and removing the /Rotate key. This method adjusts the + // various page bounding boxes (/MediaBox, etc.) so that the page will have the same semantics. + // This can be useful to work around problems with PDF applications that can't properly handle + // rotated pages. If a QPDFAcroFormDocumentHelper is provided, it will be used for resolving any + // form fields that have to be rotated. If not, one will be created inside the function, which + // is less efficient. + QPDF_DLL + void flattenRotation(QPDFAcroFormDocumentHelper* afdh = nullptr); + + // Copy annotations from another page into this page. The other page may be from the same QPDF + // or from a different QPDF. Each annotation's rectangle is transformed by the given matrix. If + // the annotation is a widget annotation that is associated with a form field, the form field is + // copied into this document's AcroForm dictionary as well. You can use this to copy annotations + // from a page that was converted to a form XObject and added to another page. For example of + // this, see examples/pdf-overlay-page.cc. This method calls + // QPDFAcroFormDocumentHelper::transformAnnotations, which will copy annotations and form fields + // so that you can copy annotations from a source page to any number of other pages, even with + // different matrices, and maintain independence from the original annotations. See also + // QPDFAcroFormDocumentHelper::fixCopiedAnnotations, which can be used if you copy a page and + // want to repair the annotations on the destination page to make them independent from the + // original page's annotations. + // + // If you pass in a QPDFAcroFormDocumentHelper*, the method will use that instead of creating + // one in the function. Creating QPDFAcroFormDocumentHelper objects is expensive, so if you're + // doing a lot of copying, it can be more efficient to create these outside and pass them in. + QPDF_DLL + void copyAnnotations( + QPDFPageObjectHelper from_page, + QPDFMatrix const& cm = QPDFMatrix(), + QPDFAcroFormDocumentHelper* afdh = nullptr, + QPDFAcroFormDocumentHelper* from_afdh = nullptr); + + private: + QPDFObjectHandle getAttribute( + std::string const& name, + bool copy_if_shared, + std::function get_fallback, + bool copy_if_fallback); + static bool + removeUnreferencedResourcesHelper(QPDFPageObjectHelper ph, std::set& unresolved); + + class Members + { + friend class QPDFPageObjectHelper; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + }; + + std::shared_ptr m; +}; + +#endif // QPDFPAGEOBJECTHELPER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFStreamFilter.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFStreamFilter.hh new file mode 100644 index 0000000..5cba242 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFStreamFilter.hh @@ -0,0 +1,67 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSTREAMFILTER_HH +#define QPDFSTREAMFILTER_HH + +#include +#include +#include + +class QPDF_DLL_CLASS QPDFStreamFilter +{ + public: + QPDFStreamFilter() = default; + + virtual ~QPDFStreamFilter() = default; + + // A QPDFStreamFilter class must implement, at a minimum, setDecodeParms() and + // getDecodePipeline(). QPDF will always call setDecodeParms() before calling + // getDecodePipeline(). It is expected that you will store any needed information from + // decode_parms (or the decode_parms object itself) in your instance so that it can be used to + // construct the decode pipeline. + + // Return a boolean indicating whether your filter can proceed with the given /DecodeParms. The + // default implementation accepts a null object and rejects everything else. + QPDF_DLL + virtual bool setDecodeParms(QPDFObjectHandle decode_parms); + + // Return a pipeline that will decode data encoded with your filter. Your implementation must + // ensure that the pipeline is deleted when the instance of your class is destroyed. + QPDF_DLL + virtual Pipeline* getDecodePipeline(Pipeline* next) = 0; + + // If your filter implements "specialized" compression or lossy compression, override one or + // both of these methods. The default implementations return false. See comments in QPDFWriter + // for details. QPDF defines specialized compression as non-lossy compression not intended for + // general-purpose data. qpdf, by default, doesn't mess with streams that are compressed with + // specialized compression, the idea being that the decision to use that compression scheme + // would fall outside of what QPDFWriter would know anything about, so any attempt to decode and + // re-encode would probably be undesirable. + QPDF_DLL + virtual bool isSpecializedCompression(); + QPDF_DLL + virtual bool isLossyCompression(); + + private: + QPDFStreamFilter(QPDFStreamFilter const&) = delete; + QPDFStreamFilter& operator=(QPDFStreamFilter const&) = delete; +}; + +#endif // QPDFSTREAMFILTER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFSystemError.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFSystemError.hh new file mode 100644 index 0000000..94e0ab0 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFSystemError.hh @@ -0,0 +1,57 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFSYSTEMERROR_HH +#define QPDFSYSTEMERROR_HH + +#include +#include +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error +{ + public: + QPDF_DLL + QPDFSystemError(std::string const& description, int system_errno); + + ~QPDFSystemError() noexcept override = default; + + // To get a complete error string, call what(), provided by std::exception. The accessors below + // return the original values used to create the exception. + + QPDF_DLL + std::string const& getDescription() const; + QPDF_DLL + int getErrno() const; + + private: + QPDF_DLL_PRIVATE + static std::string createWhat(std::string const& description, int system_errno); + + // This class does not use the Members pattern to avoid needless memory allocations during + // exception handling. + + std::string description; + int system_errno; +}; + +#endif // QPDFSYSTEMERROR_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFTokenizer.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFTokenizer.hh new file mode 100644 index 0000000..94dae1a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFTokenizer.hh @@ -0,0 +1,218 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFTOKENIZER_HH +#define QPDFTOKENIZER_HH + +#include + +#include + +#include +#include +#include + +namespace qpdf +{ + class Tokenizer; + namespace impl + { + class Parser; + } +} // namespace qpdf + +class QPDFTokenizer +{ + public: + // Token type tt_eof is only returned of allowEOF() is called on the tokenizer. tt_eof was + // introduced in QPDF version 4.1. tt_space, tt_comment, and tt_inline_image were added in QPDF + // version 8. + enum token_type_e { + tt_bad, + tt_array_close, + tt_array_open, + tt_brace_close, + tt_brace_open, + tt_dict_close, + tt_dict_open, + tt_integer, + tt_name, + tt_real, + tt_string, + tt_null, + tt_bool, + tt_word, + tt_eof, + tt_space, + tt_comment, + tt_inline_image, + }; + + class Token + { + public: + Token() : + type(tt_bad) + { + } + QPDF_DLL + Token(token_type_e type, std::string const& value); + Token( + token_type_e type, + std::string const& value, + std::string raw_value, + std::string error_message) : + type(type), + value(value), + raw_value(raw_value), + error_message(error_message) + { + } + token_type_e + getType() const + { + return this->type; + } + std::string const& + getValue() const + { + return this->value; + } + std::string const& + getRawValue() const + { + return this->raw_value; + } + std::string const& + getErrorMessage() const + { + return this->error_message; + } + bool + operator==(Token const& rhs) const + { + // Ignore fields other than type and value + return ( + (this->type != tt_bad) && (this->type == rhs.type) && (this->value == rhs.value)); + } + bool + isInteger() const + { + return this->type == tt_integer; + } + bool + isWord() const + { + return this->type == tt_word; + } + bool + isWord(std::string const& value) const + { + return this->type == tt_word && this->value == value; + } + + private: + token_type_e type; + std::string value; + std::string raw_value; + std::string error_message; + }; + + QPDF_DLL + QPDFTokenizer(); + + QPDF_DLL + ~QPDFTokenizer(); + + // If called, treat EOF as a separate token type instead of an error. This was introduced in + // QPDF 4.1 to facilitate tokenizing content streams. + QPDF_DLL + void allowEOF(); + + // If called, readToken will return "ignorable" tokens for space and comments. This was added in + // QPDF 8. + QPDF_DLL + void includeIgnorable(); + + // There are two modes of operation: push and pull. The pull method is easier but requires an + // input source. The push method is more complicated but can be used to tokenize a stream of + // incoming characters in a pipeline. + + // Push mode: + + // deprecated, please see + + // Keep presenting characters with presentCharacter() and presentEOF() and calling getToken() + // until getToken() returns true. When it does, be sure to check unread_ch and to unread ch if + // it is true. If these are called when a token is available, an exception will be thrown. + QPDF_DLL + void presentCharacter(char ch); + QPDF_DLL + void presentEOF(); + + // If a token is available, return true and initialize token with the token, unread_char with + // whether or not we have to unread the last character, and if unread_char, ch with the + // character to unread. + QPDF_DLL + bool getToken(Token& token, bool& unread_char, char& ch); + + // This function returns true of the current character is between tokens (i.e., white space that + // is not part of a string) or is part of a comment. A tokenizing filter can call this to + // determine whether to output the character. + [[deprecated("see ")]] QPDF_DLL bool + betweenTokens(); + + // Pull mode: + + // Read a token from an input source. Context describes the context in which the token is being + // read and is used in the exception thrown if there is an error. After a token is read, the + // position of the input source returned by input->tell() points to just after the token, and + // the input source's "last offset" as returned by input->getLastOffset() points to the + // beginning of the token. + QPDF_DLL + Token readToken( + InputSource& input, std::string const& context, bool allow_bad = false, size_t max_len = 0); + QPDF_DLL + Token readToken( + std::shared_ptr input, + std::string const& context, + bool allow_bad = false, + size_t max_len = 0); + + // Calling this method puts the tokenizer in a state for reading inline images. You should call + // this method after reading the character following the ID operator. In that state, it will + // return all data up to BUT NOT INCLUDING the next EI token. After you call this method, the + // next call to readToken (or the token created next time getToken returns true) will either be + // tt_inline_image or tt_bad. This is the only way readToken + // returns a tt_inline_image token. + QPDF_DLL + void expectInlineImage(std::shared_ptr input); + QPDF_DLL + void expectInlineImage(InputSource& input); + + private: + friend class qpdf::impl::Parser; + + QPDFTokenizer(QPDFTokenizer const&) = delete; + QPDFTokenizer& operator=(QPDFTokenizer const&) = delete; + + std::unique_ptr m; +}; + +#endif // QPDFTOKENIZER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFUsage.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFUsage.hh new file mode 100644 index 0000000..3c5da1b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFUsage.hh @@ -0,0 +1,36 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFUSAGE_HH +#define QPDFUSAGE_HH + +#include + +#include +#include + +class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error +{ + public: + QPDF_DLL + QPDFUsage(std::string const& msg); + ~QPDFUsage() noexcept override = default; +}; + +#endif // QPDFUSAGE_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFWriter.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFWriter.hh new file mode 100644 index 0000000..3c3c0b9 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFWriter.hh @@ -0,0 +1,455 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFWRITER_HH +#define QPDFWRITER_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace qpdf +{ + class Writer; +} + +class QPDF; + +// This class implements a simple writer for saving QPDF objects to new PDF files. See comments +// through the header file for additional details. +class QPDFWriter +{ + public: + // Construct a QPDFWriter object without specifying output. You must call one of the output + // setting routines defined below. + QPDF_DLL + QPDFWriter(QPDF& pdf); + + // Create a QPDFWriter object that writes its output to a file or to stdout. This is equivalent + // to using the previous constructor and then calling setOutputFilename(). See + // setOutputFilename() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* filename); + + // Create a QPDFWriter object that writes its output to an already open FILE*. This is + // equivalent to calling the first constructor and then calling setOutputFile(). See + // setOutputFile() for details. + QPDF_DLL + QPDFWriter(QPDF& pdf, char const* description, FILE* file, bool close_file); + + ~QPDFWriter() = default; + + class QPDF_DLL_CLASS ProgressReporter + { + public: + QPDF_DLL + virtual ~ProgressReporter(); + + // This method is called with a value from 0 to 100 to indicate approximate progress through + // the write process. See registerProgressReporter. + virtual void reportProgress(int) = 0; + }; + + // This is a progress reporter that takes a function. It is used by the C APIs, but it is + // available if you want to just register a C function as a handler. + class QPDF_DLL_CLASS FunctionProgressReporter: public ProgressReporter + { + public: + QPDF_DLL + FunctionProgressReporter(std::function); + QPDF_DLL + ~FunctionProgressReporter() override; + QPDF_DLL + void reportProgress(int) override; + + private: + std::function handler; + }; + + // Setting Output. Output may be set only one time. If you don't use the filename version of + // the QPDFWriter constructor, you must call exactly one of these methods. + + // Passing nullptr as filename means write to stdout. QPDFWriter will create a zero-length + // output file upon construction. If write fails, the empty or partially written file will not + // be deleted. This is by design: sometimes the partial file may be useful for tracking down + // problems. If your application doesn't want the partially written file to be left behind, you + // should delete it if the eventual call to write fails. + QPDF_DLL + void setOutputFilename(char const* filename); + + // Write to the given FILE*, which must be opened by the caller. If close_file is true, + // QPDFWriter will close the file. Otherwise, the caller must close the file. The file does not + // need to be seekable; it will be written to in a single pass. It must be open in binary mode. + QPDF_DLL + void setOutputFile(char const* description, FILE* file, bool close_file); + + // Indicate that QPDFWriter should create a memory buffer to contain the final PDF file. Obtain + // the memory by calling getBuffer(). + QPDF_DLL + void setOutputMemory(); + + // Return the buffer object containing the PDF file. If setOutputMemory() has been called, this + // method may be called exactly one time after write() has returned. The caller is responsible + // for deleting the buffer when done. See also getBufferSharedPointer(). + QPDF_DLL + Buffer* getBuffer(); + + // Return getBuffer() in a shared pointer. + QPDF_DLL + std::shared_ptr getBufferSharedPointer(); + + // Supply your own pipeline object. Output will be written to this pipeline, and QPDFWriter + // will call finish() on the pipeline. It is the caller's responsibility to manage the memory + // for the pipeline. The pipeline is never deleted by QPDFWriter, which makes it possible for + // you to call additional methods on the pipeline after the writing is finished. + QPDF_DLL + void setOutputPipeline(Pipeline*); + + // Setting Parameters + + // Set the value of object stream mode. In disable mode, we never generate any object streams. + // In preserve mode, we preserve object stream structure from the original file. In generate + // mode, we generate our own object streams. In all cases, we generate a conventional + // cross-reference table if there are no object streams and a cross-reference stream if there + // are object streams. The default is o_preserve. + QPDF_DLL + void setObjectStreamMode(qpdf_object_stream_e); + + // Set value of stream data mode. This is an older interface. Instead of using this, prefer + // setCompressStreams() and setDecodeLevel(). This method is retained for compatibility, but it + // does not cover the full range of available configurations. The mapping between this and the + // new methods is as follows: + // + // qpdf_s_uncompress: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_generalized) + // qpdf_s_preserve: + // setCompressStreams(false) + // setDecodeLevel(qpdf_dl_none) + // qpdf_s_compress: + // setCompressStreams(true) + // setDecodeLevel(qpdf_dl_generalized) + // + // The default is qpdf_s_compress. + QPDF_DLL + void setStreamDataMode(qpdf_stream_data_e); + + // If true, compress any uncompressed streams when writing them. Metadata streams are a special + // case and are not compressed even if this is true. This is true by default for QPDFWriter. If + // you want QPDFWriter to leave uncompressed streams uncompressed, pass false to this method. + QPDF_DLL + void setCompressStreams(bool); + + // When QPDFWriter encounters streams, this parameter controls the behavior with respect to + // attempting to apply any filters to the streams when copying to the output. The decode levels + // are as follows: + // + // qpdf_dl_none: Do not attempt to apply any filters. Streams remain as they appear in the + // original file. Note that uncompressed streams may still be compressed on output. You can + // disable that by calling setCompressStreams(false). + // + // qpdf_dl_generalized: This is the default. QPDFWriter will apply LZWDecode, ASCII85Decode, + // ASCIIHexDecode, and FlateDecode filters on the input. When combined with + // setCompressStreams(true), which is the default, the effect of this is that streams filtered + // with these older and less efficient filters will be recompressed with the Flate filter. By + // default, as a special case, if a stream is already compressed with FlateDecode and + // setCompressStreams is enabled, the original compressed data will be preserved. This behavior + // can be overridden by calling setRecompressFlate(true). + // + // qpdf_dl_specialized: In addition to uncompressing the generalized compression formats, + // supported non-lossy compression will also be decoded. At present, this includes the + // RunLengthDecode filter. + // + // qpdf_dl_all: In addition to generalized and non-lossy specialized filters, supported lossy + // compression filters will be applied. At present, this includes DCTDecode (JPEG) compression. + // Note that compressing the resulting data with DCTDecode again will accumulate loss, so avoid + // multiple compression and decompression cycles. This is mostly useful for retrieving image + // data. + QPDF_DLL + void setDecodeLevel(qpdf_stream_decode_level_e); + + // By default, when both the input and output contents of a stream are compressed with Flate, + // qpdf does not uncompress and recompress the stream. Passing true here causes it to do so. + // This can be useful if recompressing all streams with a higher compression level, which can be + // set by calling the static method Pl_Flate::setCompressionLevel. + QPDF_DLL + void setRecompressFlate(bool); + + // Set value of content stream normalization. The default is "false". If true, we attempt to + // normalize newlines inside of content streams. Some constructs such as inline images may + // thwart our efforts. There may be some cases where this can damage the content stream. This + // flag should be used only for debugging and experimenting with PDF content streams. Never use + // it for production files. + QPDF_DLL + void setContentNormalization(bool); + + // Set QDF mode. QDF mode causes special "pretty printing" of PDF objects, adds comments for + // easier perusing of files. Resulting PDF files can be edited in a text editor and then run + // through fix-qdf to update cross reference tables and stream lengths. + QPDF_DLL + void setQDFMode(bool); + + // Preserve unreferenced objects. The default behavior is to discard any object that is not + // visited during a traversal of the object structure from the trailer. + QPDF_DLL + void setPreserveUnreferencedObjects(bool); + + // Always write a newline before the endstream keyword. This helps with PDF/A compliance, though + // it is not sufficient for it. + QPDF_DLL + void setNewlineBeforeEndstream(bool); + + // Set the minimum PDF version. If the PDF version of the input file (or previously set minimum + // version) is less than the version passed to this method, the PDF version of the output file + // will be set to this value. If the original PDF file's version or previously set minimum + // version is already this version or later, the original file's version will be used. + // QPDFWriter automatically sets the minimum version to 1.4 when R3 encryption parameters are + // used, and to 1.5 when object streams are used. + QPDF_DLL + void setMinimumPDFVersion(std::string const&, int extension_level = 0); + QPDF_DLL + void setMinimumPDFVersion(PDFVersion const&); + + // Force the PDF version of the output file to be a given version. Use of this function may + // create PDF files that will not work properly with older PDF viewers. When a PDF version is + // set using this function, qpdf will use this version even if the file contains features that + // are not supported in that version of PDF. In other words, you should only use this function + // if you are sure the PDF file in question has no features of newer versions of PDF or if you + // are willing to create files that old viewers may try to open but not be able to properly + // interpret. If any encryption has been applied to the document either explicitly or by + // preserving the encryption of the source document, forcing the PDF version to a value too low + // to support that type of encryption will explicitly disable decryption. Additionally, forcing + // to a version below 1.5 will disable object streams. + QPDF_DLL + void forcePDFVersion(std::string const&, int extension_level = 0); + + // Provide additional text to insert in the PDF file somewhere near the beginning of the file. + // This can be used to add comments to the beginning of a PDF file, for example, if those + // comments are to be consumed by some other application. No checks are performed to ensure + // that the text inserted here is valid PDF. If you want to insert multiline comments, you will + // need to include \n in the string yourself and start each line with %. An extra newline will + // be appended if one is not already present at the end of your text. + QPDF_DLL + void setExtraHeaderText(std::string const&); + + // Causes a deterministic /ID value to be generated. When this is set, the current time and + // output file name are not used as part of /ID generation. Instead, a digest of all significant + // parts of the output file's contents is included in the /ID calculation. Use of a + // deterministic /ID can be handy when it is desirable for a repeat of the same qpdf operation + // on the same inputs being written to the same outputs with the same parameters to generate + // exactly the same results. This feature is incompatible with encrypted files because, for + // encrypted files, the /ID is generated before any part of the file is written since it is an + // input to the encryption process. + QPDF_DLL + void setDeterministicID(bool); + + // Cause a static /ID value to be generated. Use only in test suites. See also + // setDeterministicID. + QPDF_DLL + void setStaticID(bool); + + // Use a fixed initialization vector for AES-CBC encryption. This is not secure. It should be + // used only in test suites for creating predictable encrypted output. + QPDF_DLL + void setStaticAesIV(bool); + + // Suppress inclusion of comments indicating original object IDs when writing QDF files. This + // can also be useful for testing, particularly when using comparison of two qdf files to + // determine whether two PDF files have identical content. + QPDF_DLL + void setSuppressOriginalObjectIDs(bool); + + // Preserve encryption. The default is true unless prefiltering, content normalization, or qdf + // mode has been selected in which case encryption is never preserved. Encryption is also not + // preserved if we explicitly set encryption parameters. + QPDF_DLL + void setPreserveEncryption(bool); + + // Copy encryption parameters from another QPDF object. If you want to copy encryption from the + // object you are writing, call setPreserveEncryption(true) instead. + QPDF_DLL + void copyEncryptionParameters(QPDF&); + + // Set up for encrypted output. User and owner password both must be specified. Either or both + // may be the empty string. Note that qpdf does not apply any special treatment to the empty + // string, which makes it possible to create encrypted files with empty owner passwords and + // non-empty user passwords or with the same password for both user and owner. Some PDF reading + // products don't handle such files very well. Enabling encryption disables stream prefiltering + // and content normalization. Note that setting R2 encryption parameters sets the PDF version + // to at least 1.3, setting R3 encryption parameters pushes the PDF version number to at + // least 1.4, setting R4 parameters pushes the version to at least 1.5, or if AES is used, 1.6, + // and setting R5 or R6 parameters pushes the version to at least 1.7 with extension level 3. + // + // Note about Unicode passwords: the PDF specification requires passwords to be encoded with PDF + // Doc encoding for R <= 4 and UTF-8 for R >= 5. In all cases, these methods take strings of + // bytes as passwords. It is up to the caller to ensure that passwords are properly encoded. The + // qpdf command-line tool tries to do this, as discussed in the manual. If you are doing this + // from your own application, QUtil contains many transcoding functions that could be useful to + // you, most notably utf8_to_pdf_doc. + + // R2 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR2EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_print, + bool allow_modify, + bool allow_extract, + bool allow_annotate); + // R3 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See + // "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0 + // specification. + QPDF_DLL + void setR3EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print); + // When use_aes=false, this call enables R4 with RC4, which is a weak cryptographic algorithm. + // Even with use_aes=true, the overall encryption scheme is weak. Don't use it unless you have + // to. See "Weak Cryptography" in the manual. This encryption format is deprecated in the + // PDF 2.0 specification. + QPDF_DLL + void setR4EncryptionParametersInsecure( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata, + bool use_aes); + // R5 is deprecated. Do not use it for production use. Writing R5 is supported by qpdf + // primarily to generate test files for applications that may need to test R5 support. + QPDF_DLL + void setR5EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata); + // This is the only password-based encryption format supported by the PDF specification. + QPDF_DLL + void setR6EncryptionParameters( + char const* user_password, + char const* owner_password, + bool allow_accessibility, + bool allow_extract, + bool allow_assemble, + bool allow_annotate_and_form, + bool allow_form_filling, + bool allow_modify_other, + qpdf_r3_print_e print, + bool encrypt_metadata_aes); + + // Create linearized output. Disables qdf mode, content normalization, and stream prefiltering. + QPDF_DLL + void setLinearization(bool); + + // For debugging QPDF: provide the name of a file to write pass1 of linearization to. The only + // reason to use this is to debug QPDF. To linearize, QPDF writes out the file in two passes. + // Usually the first pass is discarded, but lots of computations are made in pass 1. If a + // linearized file comes out wrong, it can be helpful to look at the first pass. + QPDF_DLL + void setLinearizationPass1Filename(std::string const&); + + // Create PCLm output. This is only useful for clients that know how to create PCLm files. If a + // file is structured exactly as PCLm requires, this call will tell QPDFWriter to write the PCLm + // header, create certain unreferenced streams required by the standard, and write the objects + // in the required order. Calling this on an ordinary PDF serves no purpose. There is no + // command-line argument that causes this method to be called. + QPDF_DLL + void setPCLm(bool); + + // If you want to be notified of progress, derive a class from ProgressReporter and override the + // reportProgress method. + QPDF_DLL + void registerProgressReporter(std::shared_ptr); + + // Return the PDF version that will be written into the header. Calling this method does all the + // preparation for writing, so it is an error to call any methods that may cause a change to the + // version. Adding new objects to the original file after calling this may also cause problems. + // It is safe to update existing objects or stream contents after calling this method, e.g., to + // include the final version number in metadata. + QPDF_DLL + std::string getFinalVersion(); + + // Write the final file. There is no expectation of being able to call write() more than once. + QPDF_DLL + void write(); + + // Return renumbered ObjGen that was written into the final file. This method can be used after + // calling write(). + QPDF_DLL + QPDFObjGen getRenumberedObjGen(QPDFObjGen); + + // Return XRef entry that was written into the final file. This method can be used after calling + // write(). + QPDF_DLL + std::map getWrittenXRefTable(); + + // The following structs / classes are not part of the public API. + struct Object; + struct NewObject; + class ObjTable; + class NewObjTable; + + private: + friend class qpdf::Writer; + + class Members; + + std::shared_ptr m; +}; + +#endif // QPDFWRITER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFXRefEntry.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFXRefEntry.hh new file mode 100644 index 0000000..3739131 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QPDFXRefEntry.hh @@ -0,0 +1,73 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QPDFXREFENTRY_HH +#define QPDFXREFENTRY_HH + +#include +#include + +class QPDFXRefEntry +{ + public: + // Type constants are from the PDF spec section "Cross-Reference Streams": + // 0 = free entry; not used + // 1 = "uncompressed"; field 1 = offset + // 2 = "compressed"; field 1 = object stream number, field 2 = index + + // Create a type 0 "free" entry. + QPDF_DLL + QPDFXRefEntry(); + QPDF_DLL + QPDFXRefEntry(int type, qpdf_offset_t field1, int field2); + // Create a type 1 "uncompressed" entry. + QPDFXRefEntry(qpdf_offset_t offset) : + type(1), + field1(offset) + { + } + // Create a type 2 "compressed" entry. + QPDFXRefEntry(int stream_number, int index) : + type(2), + field1(stream_number), + field2(index) + { + } + + QPDF_DLL + int getType() const; + QPDF_DLL + qpdf_offset_t getOffset() const; // only for type 1 + QPDF_DLL + int getObjStreamNumber() const; // only for type 2 + QPDF_DLL + int getObjStreamIndex() const; // only for type 2 + + private: + // This class does not use the Members pattern to avoid a memory allocation for every one of + // these. A lot of these get created. + + // The layout can be changed to reduce the size from 24 to 16 bytes. However, this would have a + // definite runtime cost. + int type{0}; + qpdf_offset_t field1{0}; + int field2{0}; +}; + +#endif // QPDFXREFENTRY_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QTC.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QTC.hh new file mode 100644 index 0000000..a5ecadf --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QTC.hh @@ -0,0 +1,43 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QTC_HH +#define QTC_HH + +#include + +// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC calls in any code that +// includes this file, but QTC will still be built into the library. That way, it is possible to +// build and package qpdf with QPDF_DISABLE_QTC while still making QTC::TC available to end users. + +namespace QTC +{ + QPDF_DLL + void TC_real(char const* const scope, char const* const ccase, int n = 0); + + inline void + TC(char const* const scope, char const* const ccase, int n = 0) + { +#ifndef QPDF_DISABLE_QTC + TC_real(scope, ccase, n); +#endif // QPDF_DISABLE_QTC + } +}; // namespace QTC + +#endif // QTC_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QUtil.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QUtil.hh new file mode 100644 index 0000000..18d6083 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/QUtil.hh @@ -0,0 +1,512 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef QUTIL_HH +#define QUTIL_HH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RandomDataProvider; +class Pipeline; + +namespace QUtil +{ + // This is a collection of useful utility functions that don't really go anywhere else. + QPDF_DLL + std::string int_to_string(long long, int length = 0); + QPDF_DLL + std::string uint_to_string(unsigned long long, int length = 0); + QPDF_DLL + std::string int_to_string_base(long long, int base, int length = 0); + QPDF_DLL + std::string uint_to_string_base(unsigned long long, int base, int length = 0); + QPDF_DLL + std::string double_to_string(double, int decimal_places = 0, bool trim_trailing_zeroes = true); + + // These string to number methods throw std::runtime_error on underflow/overflow. + QPDF_DLL + long long string_to_ll(char const* str); + QPDF_DLL + int string_to_int(char const* str); + QPDF_DLL + unsigned long long string_to_ull(char const* str); + QPDF_DLL + unsigned int string_to_uint(char const* str); + + // Returns true if this exactly represents a long long. The determination is made by converting + // the string to a long long, then converting the result back to a string, and then comparing + // that result with the original string. + QPDF_DLL + bool is_long_long(char const* str); + + // Pipeline's write method wants unsigned char*, but we often have some other type of string. + // These methods do combinations of const_cast and reinterpret_cast to give us an unsigned + // char*. They should only be used when it is known that it is safe. None of the pipelines in + // qpdf modify the data passed to them, so within qpdf, it should always be safe. + QPDF_DLL + unsigned char* unsigned_char_pointer(std::string const& str); + QPDF_DLL + unsigned char* unsigned_char_pointer(char const* str); + + // Throw QPDFSystemError, which is derived from std::runtime_error, with a string formed by + // appending to "description: " the standard string corresponding to the current value of errno. + // You can retrieve the value of errno by calling getErrno() on the QPDFSystemError. Prior to + // qpdf 8.2.0, this method threw system::runtime_error directly, but since QPDFSystemError is + // derived from system::runtime_error, old code that specifically catches std::runtime_error + // will still work. + QPDF_DLL + void throw_system_error(std::string const& description); + + // The status argument is assumed to be the return value of a standard library call that sets + // errno when it fails. If status is -1, convert the current value of errno to a + // std::runtime_error that includes the standard error string. Otherwise, return status. + QPDF_DLL + int os_wrapper(std::string const& description, int status); + + // If the open fails, throws std::runtime_error. Otherwise, the FILE* is returned. The filename + // should be UTF-8 encoded, even on Windows. It will be converted as needed on Windows. + QPDF_DLL + FILE* safe_fopen(char const* filename, char const* mode); + + // The FILE* argument is assumed to be the return of fopen. If null, throw std::runtime_error. + // Otherwise, return the FILE* argument. + QPDF_DLL + FILE* fopen_wrapper(std::string const&, FILE*); + + // This is a little class to help with automatic closing files. You can do something like + // + // QUtil::FileCloser fc(QUtil::safe_fopen(filename, "rb")); + // + // and then use fc.f to the file. Be sure to actually declare a variable of type FileCloser. + // Using it as a temporary won't work because it will close the file as soon as it goes out of + // scope. + class FileCloser + { + public: + FileCloser(FILE* f) : + f(f) + { + } + + ~FileCloser() + { + if (f) { + fclose(f); + f = nullptr; + } + } + + FILE* f; + }; + + // Attempt to open the file read only and then close again + QPDF_DLL + bool file_can_be_opened(char const* filename); + + // Wrap around off_t versions of fseek and ftell if available + QPDF_DLL + int seek(FILE* stream, qpdf_offset_t offset, int whence); + QPDF_DLL + qpdf_offset_t tell(FILE* stream); + + QPDF_DLL + bool same_file(char const* name1, char const* name2); + + QPDF_DLL + void remove_file(char const* path); + + // rename_file will overwrite newname if it exists + QPDF_DLL + void rename_file(char const* oldname, char const* newname); + + // Write the contents of filename as a binary file to the pipeline. + QPDF_DLL + void pipe_file(char const* filename, Pipeline* p); + + // Return a function that will send the contents of the given file through the given pipeline as + // binary data. + QPDF_DLL + std::function file_provider(std::string const& filename); + + // Return the last path element. On Windows, either / or \ are path separators. Otherwise, only + // / is a path separator. Strip any trailing path separators. Then, if any path separators + // remain, return everything after the last path separator. Otherwise, return the whole string. + // As a special case, if a string consists entirely of path separators, the first character is + // returned. + QPDF_DLL + std::string path_basename(std::string const& filename); + + // Returns a dynamically allocated copy of a string that the caller has to delete with delete[]. + QPDF_DLL + char* copy_string(std::string const&); + + // Returns a shared_ptr with the correct deleter. + QPDF_DLL + std::shared_ptr make_shared_cstr(std::string const&); + + // Copy string as a unique_ptr to an array. + QPDF_DLL + std::unique_ptr make_unique_cstr(std::string const&); + + // Create a shared pointer to an array. From c++20, std::make_shared(n) does this. + template + std::shared_ptr + make_shared_array(size_t n) + { + return std::shared_ptr(new T[n], std::default_delete()); + } + + // Returns lower-case hex-encoded version of the string, treating each character in the input + // string as unsigned. The output string will be twice as long as the input string. + QPDF_DLL + std::string hex_encode(std::string const&); + + // Returns lower-case hex-encoded version of the char including a leading "#". + QPDF_DLL + std::string hex_encode_char(char); + + // Returns a string that is the result of decoding the input string. The input string may + // consist of mixed case hexadecimal digits. Any characters that are not hexadecimal digits will + // be silently ignored. If there are an odd number of hexadecimal digits, a trailing 0 will be + // assumed. + QPDF_DLL + std::string hex_decode(std::string const&); + + // Decode a single hex digit into a char in the range 0 <= char < 16. Return a char >= 16 if + // digit is not a valid hex digit. + QPDF_DLL + char hex_decode_char(char digit); + + // Set stdin, stdout to binary mode + QPDF_DLL + void binary_stdout(); + QPDF_DLL + void binary_stdin(); + // Set stdout to line buffered + QPDF_DLL + void setLineBuf(FILE*); + + // May modify argv0 + QPDF_DLL + char* getWhoami(char* argv0); + + // Get the value of an environment variable in a portable fashion. Returns true iff the variable + // is defined. If `value' is non-null, initializes it with the value of the variable. + QPDF_DLL + bool get_env(std::string const& var, std::string* value = nullptr); + + QPDF_DLL + time_t get_current_time(); + + // Portable structure representing a point in time with second granularity and time zone offset. + struct QPDFTime + { + QPDFTime() = default; + QPDFTime(QPDFTime const&) = default; + QPDFTime& operator=(QPDFTime const&) = default; + QPDFTime(int year, int month, int day, int hour, int minute, int second, int tz_delta) : + year(year), + month(month), + day(day), + hour(hour), + minute(minute), + second(second), + tz_delta(tz_delta) + { + } + int year; // actual year, no 1900 stuff + int month; // 1--12 + int day; // 1--31 + int hour; + int minute; + int second; + int tz_delta; // minutes before UTC + }; + + QPDF_DLL + QPDFTime get_current_qpdf_time(); + + // Convert a QPDFTime structure to a PDF timestamp string, which is "D:yyyymmddhhmmss" where + // is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone offset. may also be + // omitted. + // Examples: "D:20210207161528-05'00'", "D:20210207211528Z", "D:20210207211528". + // See get_current_qpdf_time and the QPDFTime structure above. + QPDF_DLL + std::string qpdf_time_to_pdf_time(QPDFTime const&); + + // Convert QPDFTime to a second-granularity ISO-8601 timestamp. + QPDF_DLL + std::string qpdf_time_to_iso8601(QPDFTime const&); + + // Convert a PDF timestamp string to a QPDFTime. If syntactically valid, return true and fill in + // qtm. If not valid, return false, and do not modify qtm. If qtm is null, just check the + // validity of the string. + QPDF_DLL + bool pdf_time_to_qpdf_time(std::string const&, QPDFTime* qtm = nullptr); + + // Convert PDF timestamp to a second-granularity ISO-8601 timestamp. If syntactically valid, + // return true and initialize iso8601. Otherwise, return false. + bool pdf_time_to_iso8601(std::string const& pdf_time, std::string& iso8601); + + // Return a string containing the byte representation of the UTF-8 encoding for the unicode + // value passed in. + QPDF_DLL + std::string toUTF8(unsigned long uval); + + // Return a string containing the byte representation of the UTF-16 big-endian encoding for the + // unicode value passed in. Unrepresentable code points are converted to U+FFFD. + QPDF_DLL + std::string toUTF16(unsigned long uval); + + // If utf8_val.at(pos) points to the beginning of a valid UTF-8-encoded character, return the + // codepoint of the character and set error to false. Otherwise, return 0xfffd and set error to + // true. In all cases, pos is advanced to the next position that may begin a valid character. + // When the string has been consumed, pos will be set to the string length. It is an error to + // pass a value of pos that is greater than or equal to the length of the string. + QPDF_DLL + unsigned long get_next_utf8_codepoint(std::string const& utf8_val, size_t& pos, bool& error); + + // Test whether this is a UTF-16 string. This is indicated by first two bytes being 0xFE 0xFF + // (big-endian) or 0xFF 0xFE (little-endian), each of which is the encoding of U+FEFF, the + // Unicode marker. Starting in qpdf 10.6.2, this detects little-endian as well as big-endian. + // Even though the PDF spec doesn't allow little-endian, most readers seem to accept it. + QPDF_DLL + bool is_utf16(std::string const&); + + // Test whether this is an explicit UTF-8 string as allowed by the PDF 2.0 spec. This is + // indicated by first three bytes being 0xEF 0xBB 0xBF, which is the UTF-8 encoding of U+FEFF. + QPDF_DLL + bool is_explicit_utf8(std::string const&); + + // Convert a UTF-8 encoded string to UTF-16 big-endian. Unrepresentable code points are + // converted to U+FFFD. + QPDF_DLL + std::string utf8_to_utf16(std::string const& utf8); + + // Convert a UTF-8 encoded string to the specified single-byte encoding system by replacing all + // unsupported characters with the given unknown_char. + QPDF_DLL + std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?'); + QPDF_DLL + std::string utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?'); + + // These versions return true if the conversion was successful and false if any unrepresentable + // characters were found and had to be substituted with the unknown character. + QPDF_DLL + bool utf8_to_ascii(std::string const& utf8, std::string& ascii, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_win_ansi(std::string const& utf8, std::string& win, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_mac_roman(std::string const& utf8, std::string& mac, char unknown_char = '?'); + QPDF_DLL + bool utf8_to_pdf_doc(std::string const& utf8, std::string& pdfdoc, char unknown_char = '?'); + + // Convert a UTF-16 encoded string to UTF-8. Unrepresentable code + // points are converted to U+FFFD. + QPDF_DLL + std::string utf16_to_utf8(std::string const& utf16); + + // Convert from the specified single-byte encoding system to UTF-8. There is no ascii_to_utf8 + // because all ASCII strings are already valid UTF-8. + QPDF_DLL + std::string win_ansi_to_utf8(std::string const& win); + QPDF_DLL + std::string mac_roman_to_utf8(std::string const& mac); + QPDF_DLL + std::string pdf_doc_to_utf8(std::string const& pdfdoc); + + // Analyze a string for encoding. We can't tell the difference between any single-byte + // encodings, and we can't tell for sure whether a string that happens to be valid UTF-8 isn't a + // different encoding, but we can at least tell a few things to help us guess. If there are no + // characters with the high bit set, has_8bit_chars is false, and the other values are also + // false, even though ASCII strings are valid UTF-8. is_valid_utf8 means that the string is + // non-trivially valid UTF-8. Although the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and + // just about everything else) accepts UTF-16LE (as of 10.6.2). + QPDF_DLL + void analyze_encoding( + std::string const& str, bool& has_8bit_chars, bool& is_valid_utf8, bool& is_utf16); + + // Try to compensate for previously incorrectly encoded strings. We want to compensate for the + // following errors: + // + // * The string was supposed to be UTF-8 but was one of the single-byte encodings + // * The string was supposed to be PDF Doc but was either UTF-8 or one of the other single-byte + // encodings + // + // The returned vector always contains the original string first, and then it contains what the + // correct string would be in the event that the original string was the result of any of the + // above errors. + // + // This method is useful for attempting to recover a password that may have been previously + // incorrectly encoded. For example, the password was supposed to be UTF-8 but the previous + // application used a password encoded in WinAnsi, or if the previous password was supposed to + // be PDFDoc but was actually given as UTF-8 or WinAnsi, this method would find the correct + // password. + QPDF_DLL + std::vector possible_repaired_encodings(std::string); + + // Return a cryptographically secure random number. + QPDF_DLL + long random(); + + // Initialize a buffer with cryptographically secure random bytes. + QPDF_DLL + void initializeWithRandomBytes(unsigned char* data, size_t len); + + // Supply a random data provider. Starting in qpdf 10.0.0, qpdf uses the crypto provider as its + // source of random numbers. If you are using the native crypto provider, then qpdf will either + // use the operating system's secure random number source or, only if enabled at build time, an + // insecure random source from stdlib. The caller is responsible for managing the memory for the + // RandomDataProvider. This method modifies a static variable. If you are providing your own + // random data provider, you should call this at the beginning of your program before creating + // any QPDF objects. Passing a null to this method will reset the library back to its default + // random data provider. + QPDF_DLL + void setRandomDataProvider(RandomDataProvider*); + + // This returns the random data provider that would be used the next time qpdf needs random + // data. It will never return null. If no random data provider has been provided and the + // library was not compiled with any random data provider available, an exception will be + // thrown. + QPDF_DLL + RandomDataProvider* getRandomDataProvider(); + + // Filename is UTF-8 encoded, even on Windows, as described in the comments for safe_fopen. + QPDF_DLL + std::list read_lines_from_file(char const* filename, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(std::istream&, bool preserve_eol = false); + QPDF_DLL + std::list read_lines_from_file(FILE*, bool preserve_eol = false); + QPDF_DLL + void read_lines_from_file( + std::function next_char, + std::list& lines, + bool preserve_eol = false); + + QPDF_DLL + void read_file_into_memory(char const* filename, std::shared_ptr& file_buf, size_t& size); + + QPDF_DLL + std::string read_file_into_string(char const* filename); + QPDF_DLL + std::string read_file_into_string(FILE* f, std::string_view filename = ""); + + // This used to be called strcasecmp, but that is a macro on some platforms, so we have to give + // it a name that is not likely to be a macro anywhere. + QPDF_DLL + int str_compare_nocase(char const*, char const*); + + // These routines help the tokenizer recognize certain character classes without using ctype, + // which we avoid because of locale considerations. + QPDF_DLL + bool is_hex_digit(char); + + QPDF_DLL + bool is_space(char); + + QPDF_DLL + bool is_digit(char); + + QPDF_DLL + bool is_number(char const*); + + /// @brief Handles the result code from qpdf functions. + /// + /// **For qpdf internal use only - not part of the public API** + /// @par + /// Depending on the result code, either continues execution or throws an + /// exception in case of an invalid parameter. + /// + /// @param result The result code of type qpdf_result_e, indicating success or failure status. + /// @param context A string describing the context where this function is invoked, used for + /// error reporting if an exception is thrown. + /// + /// @throws std::logic_error If the result code is `qpdf_bad_parameter`, indicating an invalid + /// parameter was supplied to a function. The exception message will + /// include the provided context for easier debugging. + /// + /// @since 12.3 + QPDF_DLL + void handle_result_code(qpdf_result_e result, std::string_view context); + + // This method parses the numeric range syntax used by the qpdf command-line tool. May throw + // std::runtime_error. A numeric range is as comma-separated list of groups. A group may be a + // number specification or a range of number specifications separated by a dash. A number + // specification may be one of the following (where is a number): + // * -- the numeric value of n + // * z -- the value of the `max` parameter + // * r -- represents max + 1 - ( from the end) + // + // If the group is two number specifications separated by a dash, it represents the range of + // numbers from the first to the second, inclusive. If the first is greater than the second, the + // numbers are descending. + // + // From qpdf 11.7.1: if a group starts with `x`, its members are excluded from the previous + // group that didn't start with `x1. + // + // Example: with max of 15, the range "4-10,x7-9,12-8,xr5" is 4, 5, 6, 10, 12, 10, 9, 8. This is + // 4 through 10 inclusive without 7 through 9 inclusive followed by 12 to 8 inclusive + // (descending) without 11 (the fifth value counting backwards from 15). For more information + // and additional examples, see the "Page Ranges" section in the manual. + QPDF_DLL + std::vector parse_numrange(char const* range, int max); + +#ifndef QPDF_NO_WCHAR_T + // If you are building qpdf on a stripped down system that doesn't have wchar_t, such as may be + // the case in some embedded environments, you may define QPDF_NO_WCHAR_T in your build. This + // symbol is never defined automatically. Search for wchar_t in qpdf's top-level README.md file + // for details. + + // Take an argv array consisting of wchar_t, as when wmain is invoked, convert all UTF-16 + // encoded strings to UTF-8, and call another main. + QPDF_DLL + int call_main_from_wmain(int argc, wchar_t* argv[], std::function realmain); + QPDF_DLL + int call_main_from_wmain( + int argc, + wchar_t const* const argv[], + std::function realmain); +#endif // QPDF_NO_WCHAR_T + + // Try to return the maximum amount of memory allocated by the current process and its threads. + // Return 0 if unable to determine. This is Linux-specific and not implemented to be completely + // reliable. It is used during development for performance testing to detect changes that may + // significantly change memory usage. It is not recommended for use for other purposes. + QPDF_DLL + size_t get_max_memory_usage(); +}; // namespace QUtil + +#endif // QUTIL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/RandomDataProvider.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/RandomDataProvider.hh new file mode 100644 index 0000000..c929f0f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/RandomDataProvider.hh @@ -0,0 +1,44 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef RANDOMDATAPROVIDER_HH +#define RANDOMDATAPROVIDER_HH + +#include +#include // for size_t + +class QPDF_DLL_CLASS RandomDataProvider +{ + public: + virtual ~RandomDataProvider() = default; + virtual void provideRandomData(unsigned char* data, size_t len) = 0; + + protected: + QPDF_DLL_PRIVATE + RandomDataProvider() = default; + + private: + RandomDataProvider(RandomDataProvider const&) = delete; + RandomDataProvider& operator=(RandomDataProvider const&) = delete; +}; + +#endif // RANDOMDATAPROVIDER_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Types.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Types.h new file mode 100644 index 0000000..015cd22 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/Types.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Versions of qpdf prior to version 7 were released under the terms + * of version 2.0 of the Artistic License. At your option, you may + * continue to consider qpdf to be licensed under those terms. Please + * see the manual for additional information. + */ + +#ifndef QPDFTYPES_H +#define QPDFTYPES_H + +/* Provide an offset type that should be as big as off_t on just about + * any system. If your compiler doesn't support C99 (or at least the + * "long long" type), then you may have to modify this definition. + */ + +typedef long long int qpdf_offset_t; + +#endif /* QPDFTYPES_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_att.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_att.hh new file mode 100644 index 0000000..ea85419 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_att.hh @@ -0,0 +1,14 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL AttConfig* replace(); +QPDF_DLL AttConfig* key(std::string const& parameter); +QPDF_DLL AttConfig* filename(std::string const& parameter); +QPDF_DLL AttConfig* creationdate(std::string const& parameter); +QPDF_DLL AttConfig* moddate(std::string const& parameter); +QPDF_DLL AttConfig* mimetype(std::string const& parameter); +QPDF_DLL AttConfig* description(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_copy_att.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_copy_att.hh new file mode 100644 index 0000000..764a5ea --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_copy_att.hh @@ -0,0 +1,9 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL CopyAttConfig* prefix(std::string const& parameter); +QPDF_DLL CopyAttConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_enc.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_enc.hh new file mode 100644 index 0000000..ed4d071 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_enc.hh @@ -0,0 +1,20 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL EncConfig* extract(std::string const& parameter); +QPDF_DLL EncConfig* annotate(std::string const& parameter); +QPDF_DLL EncConfig* print(std::string const& parameter); +QPDF_DLL EncConfig* modify(std::string const& parameter); +QPDF_DLL EncConfig* cleartextMetadata(); +QPDF_DLL EncConfig* forceV4(); +QPDF_DLL EncConfig* accessibility(std::string const& parameter); +QPDF_DLL EncConfig* assemble(std::string const& parameter); +QPDF_DLL EncConfig* form(std::string const& parameter); +QPDF_DLL EncConfig* modifyOther(std::string const& parameter); +QPDF_DLL EncConfig* useAes(std::string const& parameter); +QPDF_DLL EncConfig* forceR5(); +QPDF_DLL EncConfig* allowInsecure(); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_global.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_global.hh new file mode 100644 index 0000000..7f8758b --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_global.hh @@ -0,0 +1,13 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL GlobalConfig* noDefaultLimits(); +QPDF_DLL GlobalConfig* parserMaxContainerSize(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxContainerSizeDamaged(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxErrors(std::string const& parameter); +QPDF_DLL GlobalConfig* parserMaxNesting(std::string const& parameter); +QPDF_DLL GlobalConfig* maxStreamFilters(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_limits.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_limits.hh new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_main.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_main.hh new file mode 100644 index 0000000..0ed4f64 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_main.hh @@ -0,0 +1,97 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL Config* allowWeakCrypto(); +QPDF_DLL Config* check(); +QPDF_DLL Config* checkLinearization(); +QPDF_DLL Config* coalesceContents(); +QPDF_DLL Config* decrypt(); +QPDF_DLL Config* deterministicId(); +QPDF_DLL Config* externalizeInlineImages(); +QPDF_DLL Config* filteredStreamData(); +QPDF_DLL Config* flattenRotation(); +QPDF_DLL Config* generateAppearances(); +QPDF_DLL Config* ignoreXrefStreams(); +QPDF_DLL Config* isEncrypted(); +QPDF_DLL Config* jsonInput(); +QPDF_DLL Config* keepInlineImages(); +QPDF_DLL Config* linearize(); +QPDF_DLL Config* listAttachments(); +QPDF_DLL Config* newlineBeforeEndstream(); +QPDF_DLL Config* noOriginalObjectIds(); +QPDF_DLL Config* noWarn(); +QPDF_DLL Config* optimizeImages(); +QPDF_DLL Config* passwordIsHexKey(); +QPDF_DLL Config* preserveUnreferenced(); +QPDF_DLL Config* preserveUnreferencedResources(); +QPDF_DLL Config* progress(); +QPDF_DLL Config* qdf(); +QPDF_DLL Config* rawStreamData(); +QPDF_DLL Config* recompressFlate(); +QPDF_DLL Config* removeAcroform(); +QPDF_DLL Config* removeInfo(); +QPDF_DLL Config* removeMetadata(); +QPDF_DLL Config* removePageLabels(); +QPDF_DLL Config* removeStructure(); +QPDF_DLL Config* reportMemoryUsage(); +QPDF_DLL Config* requiresPassword(); +QPDF_DLL Config* removeRestrictions(); +QPDF_DLL Config* showEncryption(); +QPDF_DLL Config* showEncryptionKey(); +QPDF_DLL Config* showLinearization(); +QPDF_DLL Config* showNpages(); +QPDF_DLL Config* showPages(); +QPDF_DLL Config* showXref(); +QPDF_DLL Config* staticAesIv(); +QPDF_DLL Config* staticId(); +QPDF_DLL Config* suppressPasswordRecovery(); +QPDF_DLL Config* suppressRecovery(); +QPDF_DLL Config* testJsonSchema(); +QPDF_DLL Config* verbose(); +QPDF_DLL Config* warningExit0(); +QPDF_DLL Config* withImages(); +QPDF_DLL Config* compressionLevel(std::string const& parameter); +QPDF_DLL Config* jpegQuality(std::string const& parameter); +QPDF_DLL Config* copyEncryption(std::string const& parameter); +QPDF_DLL Config* encryptionFilePassword(std::string const& parameter); +QPDF_DLL Config* forceVersion(std::string const& parameter); +QPDF_DLL Config* iiMinBytes(std::string const& parameter); +QPDF_DLL Config* jobJsonFile(std::string const& parameter); +QPDF_DLL Config* jsonObject(std::string const& parameter); +QPDF_DLL Config* keepFilesOpenThreshold(std::string const& parameter); +QPDF_DLL Config* linearizePass1(std::string const& parameter); +QPDF_DLL Config* minVersion(std::string const& parameter); +QPDF_DLL Config* oiMinArea(std::string const& parameter); +QPDF_DLL Config* oiMinHeight(std::string const& parameter); +QPDF_DLL Config* oiMinWidth(std::string const& parameter); +QPDF_DLL Config* password(std::string const& parameter); +QPDF_DLL Config* passwordFile(std::string const& parameter); +QPDF_DLL Config* removeAttachment(std::string const& parameter); +QPDF_DLL Config* rotate(std::string const& parameter); +QPDF_DLL Config* showAttachment(std::string const& parameter); +QPDF_DLL Config* showObject(std::string const& parameter); +QPDF_DLL Config* jsonStreamPrefix(std::string const& parameter); +QPDF_DLL Config* updateFromJson(std::string const& parameter); +QPDF_DLL Config* collate(std::string const& parameter); +QPDF_DLL Config* collate(); +QPDF_DLL Config* splitPages(std::string const& parameter); +QPDF_DLL Config* splitPages(); +QPDF_DLL Config* compressStreams(std::string const& parameter); +QPDF_DLL Config* decodeLevel(std::string const& parameter); +QPDF_DLL Config* flattenAnnotations(std::string const& parameter); +QPDF_DLL Config* jsonKey(std::string const& parameter); +QPDF_DLL Config* jsonStreamData(std::string const& parameter); +QPDF_DLL Config* keepFilesOpen(std::string const& parameter); +QPDF_DLL Config* normalizeContent(std::string const& parameter); +QPDF_DLL Config* objectStreams(std::string const& parameter); +QPDF_DLL Config* passwordMode(std::string const& parameter); +QPDF_DLL Config* removeUnreferencedResources(std::string const& parameter); +QPDF_DLL Config* streamData(std::string const& parameter); +QPDF_DLL Config* json(std::string const& parameter); +QPDF_DLL Config* json(); +QPDF_DLL Config* jsonOutput(std::string const& parameter); +QPDF_DLL Config* jsonOutput(); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_pages.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_pages.hh new file mode 100644 index 0000000..75b0ae5 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_pages.hh @@ -0,0 +1,10 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL PagesConfig* file(std::string const& parameter); +QPDF_DLL PagesConfig* range(std::string const& parameter); +QPDF_DLL PagesConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_set_page_labels.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_set_page_labels.hh new file mode 100644 index 0000000..b816d29 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_set_page_labels.hh @@ -0,0 +1,7 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_uo.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_uo.hh new file mode 100644 index 0000000..547ecf3 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/auto_job_c_uo.hh @@ -0,0 +1,12 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +// clang-format off +// +QPDF_DLL UOConfig* file(std::string const& parameter); +QPDF_DLL UOConfig* to(std::string const& parameter); +QPDF_DLL UOConfig* from(std::string const& parameter); +QPDF_DLL UOConfig* repeat(std::string const& parameter); +QPDF_DLL UOConfig* password(std::string const& parameter); diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/global.hh b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/global.hh new file mode 100644 index 0000000..b99ee31 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/global.hh @@ -0,0 +1,264 @@ +// Copyright (c) 2005-2021 Jay Berkenbilt +// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under +// the License. +// +// Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic +// License. At your option, you may continue to consider qpdf to be licensed under those terms. +// Please see the manual for additional information. + +#ifndef GLOBAL_HH +#define GLOBAL_HH + +#include + +#include +#include + +#include + +namespace qpdf::global +{ + /// Helper function to translate result codes into C++ exceptions - for qpdf internal use only. + inline void + handle_result(qpdf_result_e result) + { + if (result != qpdf_r_ok) { + QUtil::handle_result_code(result, "qpdf::global"); + } + } + + /// Helper function to wrap calls to qpdf_global_get_uint32 - for qpdf internal use only. + inline uint32_t + get_uint32(qpdf_param_e param) + { + uint32_t value; + handle_result(qpdf_global_get_uint32(param, &value)); + return value; + } + + /// Helper function to wrap calls to qpdf_global_set_uint32 - for qpdf internal use only. + inline void + set_uint32(qpdf_param_e param, uint32_t value) + { + handle_result(qpdf_global_set_uint32(param, value)); + } + + /// @brief Retrieves the number of limit errors. + /// + /// Returns the number of times a global limit was exceeded. This item is read only. + /// + /// @return The number of limit errors. + /// + /// @since 12.3 + uint32_t inline limit_errors() + { + return get_uint32(qpdf_p_limit_errors); + } + + namespace options + { + /// @brief Retrieves whether inspection mode is set. + /// + /// @return True if inspection mode is set. + /// + /// @since 12.3 + bool inline inspection_mode() + { + return get_uint32(qpdf_p_inspection_mode) != 0; + } + + /// @brief Set inspection mode if `true` is passed. + /// + /// This function enables restrictive inspection mode if `true` is passed. Inspection mode + /// must be enabled before a QPDF object is created. By default inspection mode is off. + /// Calling `inspection_mode(false)` is not supported and currently is a no-op. + /// + /// @param value A boolean indicating whether to enable (true) inspection mode. + /// + /// @since 12.3 + void inline inspection_mode(bool value) + { + set_uint32(qpdf_p_inspection_mode, value ? QPDF_TRUE : QPDF_FALSE); + } + + /// @brief Retrieves whether default limits are enabled. + /// + /// @return True if default limits are enabled. + /// + /// @since 12.3 + bool inline default_limits() + { + return get_uint32(qpdf_p_default_limits) != 0; + } + + /// @brief Disable all optional default limits if `false` is passed. + /// + /// This function disables all optional default limits if `false` is passed. Once default + /// values have been disabled they cannot be re-enabled. Passing `true` has no effect. This + /// function will leave any limits that have been explicitly set unchanged. Some limits, + /// such as limits imposed to avoid stack overflows, cannot be disabled but can be changed. + /// + /// @param value A boolean indicating whether to disable (false) the default limits. + /// + /// @since 12.3 + void inline default_limits(bool value) + { + set_uint32(qpdf_p_default_limits, value ? QPDF_TRUE : QPDF_FALSE); + } + + } // namespace options + + namespace limits + { + /// @brief Retrieves the maximum nesting level while parsing objects. + /// + /// @return The maximum nesting level while parsing objects. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + uint32_t inline parser_max_nesting() + { + return get_uint32(qpdf_p_parser_max_nesting); + } + + /// @brief Sets the maximum nesting level while parsing objects. + /// + /// @param value The maximum nesting level to set. + /// + /// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`. + /// + /// @since 12.3 + void inline parser_max_nesting(uint32_t value) + { + set_uint32(qpdf_p_parser_max_nesting, value); + } + + /// @brief Retrieves the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @return The maximum number of errors allowed while parsing objects. + /// + /// @since 12.3 + uint32_t inline parser_max_errors() + { + return get_uint32(qpdf_p_parser_max_errors); + } + + /// Sets the maximum number of errors allowed while parsing objects. + /// + /// A value of 0 means that there is no maximum imposed. + /// + /// @param value The maximum number of errors allowed while parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_errors(uint32_t value) + { + set_uint32(qpdf_p_parser_max_errors, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size() + { + return get_uint32(qpdf_p_parser_max_container_size); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is undamaged and the object itself + /// can be parsed without errors. The default limit is 4,294,967,295. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size, value); + } + + /// @brief Retrieves the maximum number of top-level objects allowed in a container while + /// parsing objects. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing xref streams. The default limit is 5,000. + /// + /// @return The maximum number of top-level objects allowed in a container while parsing + /// objects. + /// + /// @since 12.3 + uint32_t inline parser_max_container_size_damaged() + { + return get_uint32(qpdf_p_parser_max_container_size_damaged); + } + + /// @brief Sets the maximum number of top-level objects allowed in a container while + /// parsing. + /// + /// The limit applies when the PDF document's xref table is damaged or the object itself is + /// damaged. The limit also applies when parsing trailer dictionaries and xref streams. The + /// default limit is 5,000. + /// + /// @param value The maximum number of top-level objects allowed in a container while + /// parsing objects to set. + /// + /// @since 12.3 + void inline parser_max_container_size_damaged(uint32_t value) + { + set_uint32(qpdf_p_parser_max_container_size_damaged, value); + } + + /// @brief Retrieves the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @return The maximum number of filters allowed when filtering streams. + /// + /// @since 12.3 + uint32_t inline max_stream_filters() + { + return get_uint32(qpdf_p_max_stream_filters); + } + + /// @brief Sets the maximum number of filters allowed when filtering streams. + /// + /// An excessive number of stream filters is usually a sign that a file is damaged or + /// specially constructed. If the maximum is exceeded for a stream the stream is treated as + /// unfilterable. The default maximum is 25. + /// + /// @param value The maximum number of filters allowed when filtering streams to set. + /// + /// @since 12.3 + void inline max_stream_filters(uint32_t value) + { + set_uint32(qpdf_p_max_stream_filters, value); + } + } // namespace limits + +} // namespace qpdf::global + +#endif // GLOBAL_HH diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdf-c.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdf-c.h new file mode 100644 index 0000000..c602f9f --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdf-c.h @@ -0,0 +1,1070 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDF_C_H +#define QPDF_C_H + +/* + * This file defines a basic "C" API for qpdf. It provides access to a subset of the QPDF library's + * capabilities to make them accessible to callers who can't handle calling C++ functions or working + * with C++ classes. This may be especially useful to Windows users who are accessing the qpdf DLL + * directly or to other people programming in non-C/C++ languages that can call C code but not C++ + * code. Starting with qpdf 11.7, it is possible to write your own `extern "C"` functions that + * interoperate with the C API. + * + * There are several things to keep in mind when using the C API. + * + * Error handling is tricky because the underlying C++ API uses exception handling. See "ERROR + * HANDLING" below for a detailed explanation. + * + * The C API is not as rich as the C++ API. For many operations, you must use the C++ API. The C + * API is primarily useful for doing basic transformations on PDF files similar to what you + * might do with the qpdf command-line tool. You can write your own `extern "C"` functions in + * C++ that interoperate with the C API by using qpdf_c_get_qpdf and qpdf_c_wrap which were + * introduced in qpdf 11.7.0. + * + * These functions store their state in a qpdf_data object. Individual instances of qpdf_data + * are not thread-safe: although you may access different qpdf_data objects from different + * threads, you may not access one qpdf_data simultaneously from multiple threads. + * + * All dynamic memory, except for that of the qpdf_data object itself, is managed by the library + * unless otherwise noted. You must create a qpdf_data object using qpdf_init and free it using + * qpdf_cleanup. + * + * Many functions return char*. In all cases, the char* values returned are pointers to data + * inside the qpdf_data object. As such, they are always freed by qpdf_cleanup. In most cases, + * strings returned by functions here may be invalidated by subsequent function calls, sometimes + * even to different functions. If you want a string to last past the next qpdf call or after a + * call to qpdf_cleanup, you should make a copy of it. + * + * Since it is possible for a PDF string to contain null characters, a function that returns + * data originating from a PDF string may also contain null characters. To handle that case, you + * call qpdf_get_last_string_length() to get the length of whatever string was just returned. + * See STRING FUNCTIONS below. + * + * Most functions defined here have obvious counterparts that are methods to either QPDF or + * QPDFWriter. Please see comments in QPDF.hh and QPDFWriter.hh for details on their use. In + * order to avoid duplication of information, comments here focus primarily on differences + * between the C and C++ API. + */ + +/* ERROR HANDLING -- changed in qpdf 10.5 */ + +/* SUMMARY: The only way to know whether a function that does not return an error code has + * encountered an error is to call qpdf_has_error after each function. You can do this even for + * functions that do return error codes. You can also call qpdf_silence_errors to prevent qpdf from + * writing these errors to stderr. + * + * DETAILS: + * + * The data type underlying qpdf_data maintains a list of warnings and a single error. To retrieve + * warnings, call qpdf_next_warning while qpdf_more_warnings is true. To retrieve the error, call + * qpdf_get_error when qpdf_has_error is true. + * + * There are several things that are important to understand. + * + * Some functions return an error code. The value of the error code is made up of a bitwise-OR of + * QPDF_WARNINGS and QPDF_ERRORS. The QPDF_ERRORS bit is set if there was an error during the *most + * recent call* to the API. The QPDF_WARNINGS bit is set if there are any warnings that have not yet + * been retrieved by calling qpdf_more_warnings. It is possible for both its or neither bit to be + * set. + * + * The expected mode of operation is to go through a series of operations, checking for errors after + * each call, but only checking for warnings at the end. This is similar to how it works in the C++ + * API where warnings are handled in exactly this way but errors result in exceptions being thrown. + * However, in both the C and C++ API, it is possible to check for and handle warnings as they + * arise. + * + * Some functions return values (or void) rather than an error code. This is especially true with + * the object handling functions. Those functions can still generate errors. To handle errors in + * those cases, you should explicitly call qpdf_has_error(). Note that, if you want to avoid the + * inconsistencies in the interface, you can always check for error conditions in this way rather + * than looking at status return codes. + * + * Prior to qpdf 10.5, if one of the functions that does not return an error code encountered an + * exception, it would cause the entire program to crash. Starting in qpdf 10.5, the default + * response to an error condition in these situations is to print the error to standard error, issue + * exactly one warning indicating that such an error occurred, and return a sensible fallback value + * (0 for numbers, QPDF_FALSE for booleans, "" for strings, or a null or uninitialized object + * handle). This is better than the old behavior but still undesirable as the best option is to + * explicitly check for error conditions. + * + * To prevent qpdf from writing error messages to stderr in this way, you can call + * qpdf_silence_errors(). This signals to the qpdf library that you intend to check the error codes + * yourself. + * + * If you encounter a situation where an exception from the C++ code is not properly converted to an + * error as described above, it is a bug in qpdf, which should be reported at + * https://github.com/qpdf/qpdf/issues/new. + */ + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _qpdf_data* qpdf_data; + typedef struct _qpdf_error* qpdf_error; + + /* Many functions return an integer error code. Codes are defined below. See comments at the + * top of the file for details. Note that the values below can be logically orred together. + */ + typedef int QPDF_ERROR_CODE; +#define QPDF_SUCCESS 0 +#define QPDF_WARNINGS 1 << 0 +#define QPDF_ERRORS 1 << 1 + + typedef int QPDF_BOOL; +#define QPDF_TRUE 1 +#define QPDF_FALSE 0 + + /* From qpdf 10.5: call this method to signal to the library that you are explicitly handling + * errors from functions that don't return error codes. Otherwise, the library will print these + * error conditions to stderr and issue a warning. Prior to 10.5, the program would have + * crashed from an unhandled exception. + */ + QPDF_DLL + void qpdf_silence_errors(qpdf_data qpdf); + + /* Returns the version of the qpdf software. This is guaranteed to be a static value. + */ + QPDF_DLL + char const* qpdf_get_qpdf_version(); + + /* Returns dynamically allocated qpdf_data pointer; must be freed by calling qpdf_cleanup. You + * must call qpdf_read, one of the other qpdf_read_* functions, or qpdf_empty_pdf before calling + * any function that would need to operate on the PDF file. + */ + QPDF_DLL + qpdf_data qpdf_init(); + + /* Pass a pointer to the qpdf_data pointer created by qpdf_init to clean up resources. This does + * not include buffers initialized by functions that return stream data but it otherwise + * includes all data associated with the QPDF object or any object handles. + */ + QPDF_DLL + void qpdf_cleanup(qpdf_data* qpdf); + + /* ERROR REPORTING */ + + /* Returns 1 if there is an error condition. The error condition can be retrieved by a single + * call to qpdf_get_error. + */ + QPDF_DLL + QPDF_BOOL qpdf_has_error(qpdf_data qpdf); + + /* Returns the error condition, if any. The return value is a pointer to data that will become + * invalid after the next call to this function, qpdf_next_warning, or qpdf_cleanup. After this + * function is called, qpdf_has_error will return QPDF_FALSE until the next error condition + * occurs. If there is no error condition, this function returns a null pointer. + */ + QPDF_DLL + qpdf_error qpdf_get_error(qpdf_data qpdf); + + /* Returns 1 if there are any unretrieved warnings, and zero otherwise. + */ + QPDF_DLL + QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf); + + /* If there are any warnings, returns a pointer to the next warning. Otherwise returns a null + * pointer. + */ + QPDF_DLL + qpdf_error qpdf_next_warning(qpdf_data qpdf); + + /* Extract fields of the error. */ + + /* Use this function to get a full error message suitable for showing to the user. */ + QPDF_DLL + char const* qpdf_get_error_full_text(qpdf_data q, qpdf_error e); + + /* Use these functions to extract individual fields from the error; see QPDFExc.hh for details. + */ + QPDF_DLL + enum qpdf_error_code_e qpdf_get_error_code(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_filename(qpdf_data q, qpdf_error e); + QPDF_DLL + unsigned long long qpdf_get_error_file_position(qpdf_data q, qpdf_error e); + QPDF_DLL + char const* qpdf_get_error_message_detail(qpdf_data q, qpdf_error e); + + /* By default, warnings are written to stderr. Passing true to this function will prevent + * warnings from being written to stderr. They will still be available by calls to + * qpdf_next_warning. + */ + QPDF_DLL + void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value); + + /* LOG FUNCTIONS */ + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdf_set_logger(qpdf_data qpdf, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdf_get_logger(qpdf_data qpdf); + + /* CHECK FUNCTIONS */ + + /* Attempt to read the entire PDF file to see if there are any errors qpdf can detect. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf); + + /* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */ + + QPDF_DLL + void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value); + + /* PROCESS FUNCTIONS */ + + /* This functions process a PDF or JSON input source. */ + + /* Calling qpdf_read causes processFile to be called in the C++ API. Basic parsing is + * performed, but data from the file is only read as needed. For files without passwords, pass + * a null pointer or an empty string as the password. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_read(qpdf_data qpdf, char const* filename, char const* password); + + /* Calling qpdf_read_memory causes processMemoryFile to be called in the C++ API. Otherwise, it + * behaves in the same way as qpdf_read. The description argument will be used in place of the + * file name in any error or warning messages generated by the library. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_read_memory( + qpdf_data qpdf, + char const* description, + char const* buffer, + unsigned long long size, + char const* password); + + /* Calling qpdf_empty_pdf initializes this qpdf object with an empty PDF, making it possible to + * create a PDF from scratch using the C API. Added in 10.6. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf); + + /* Create a PDF from a JSON file. This calls createFromJSON in the C++ API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_file(qpdf_data qpdf, char const* filename); + + /* Create a PDF from JSON data in a null-terminated string. This calls createFromJSON in the C++ + * API. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* JSON UPDATE FUNCTIONS */ + + /* Update a QPDF object from a JSON file or buffer. These functions call updateFromJSON. One of + * the other processing functions has to be called first so that the QPDF object is initialized + * with PDF data. + */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_file(qpdf_data qpdf, char const* filename); + QPDF_DLL + QPDF_ERROR_CODE + qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size); + + /* READ FUNCTIONS */ + + /* Read functions below must be called after qpdf_read or any of the other functions that + * process a PDF. */ + + /* + * NOTE: Functions that return char* are returning a pointer to an internal buffer that will be + * reused for each call to a function that returns a char*. You must use or copy the value + * before calling any other qpdf library functions. + */ + + /* Return the version of the PDF file. See warning above about functions that return char*. */ + QPDF_DLL + char const* qpdf_get_pdf_version(qpdf_data qpdf); + + /* Return the extension level of the PDF file. */ + QPDF_DLL + int qpdf_get_pdf_extension_level(qpdf_data qpdf); + + /* Return the user password. If the file is opened using the owner password, the user password + * may be retrieved using this function. If the file is opened using the user password, this + * function will return that user password. See warning above about functions that return + * char*. + */ + QPDF_DLL + char const* qpdf_get_user_password(qpdf_data qpdf); + + /* Return the string value of a key in the document's Info dictionary. The key parameter should + * include the leading slash, e.g. "/Author". If the key is not present or has a non-string + * value, a null pointer is returned. Otherwise, a pointer to an internal buffer is returned. + * See warning above about functions that return char*. + */ + QPDF_DLL + char const* qpdf_get_info_key(qpdf_data qpdf, char const* key); + + /* Set a value in the info dictionary, possibly replacing an existing value. The key must + * include the leading slash (e.g. "/Author"). Passing a null pointer as a value will remove + * the key from the info dictionary. Otherwise, a copy will be made of the string that is + * passed in. + */ + QPDF_DLL + void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value); + + /* Indicate whether the input file is linearized. */ + QPDF_DLL + QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf); + + /* Indicate whether the input file is encrypted. */ + QPDF_DLL + QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf); + + QPDF_DLL + QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf); + QPDF_DLL + QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf); + + /* JSON WRITE FUNCTIONS */ + + /* This function serializes the PDF to JSON. This calls writeJSON from the C++ API. + * + * - version: the JSON version, currently must be 2 + * - fn: a function that will be called with blocks of JSON data; will be called with data, a + * length, and the value of the udata parameter to this function + * - udata: will be passed as the third argument to fn with each call; use this for your own + * tracking or pass a null pointer if you don't need it + * - For decode_level, json_stream_data, file_prefix, and wanted_objects, see comments in + * QPDF.hh. For this API, wanted_objects should be a null-terminated array of null-terminated + * strings. Pass a null pointer if you want all objects. + */ + + /* Function should return 0 on success. */ + typedef int (*qpdf_write_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + QPDF_ERROR_CODE qpdf_write_json( + qpdf_data qpdf, + int version, + qpdf_write_fn_t fn, + void* udata, + enum qpdf_stream_decode_level_e decode_level, + enum qpdf_json_stream_data_e json_stream_data, + char const* file_prefix, + char const* const* wanted_objects); + + /* WRITE FUNCTIONS */ + + /* Set up for writing. No writing is actually performed until the call to qpdf_write(). + */ + + /* Supply the name of the file to be written and initialize the qpdf_data object to handle + * writing operations. This function also attempts to create the file. The PDF data is not + * written until the call to qpdf_write. qpdf_init_write may be called multiple times for the + * same qpdf_data object. When qpdf_init_write is called, all information from previous calls + * to functions that set write parameters (qpdf_set_linearization, etc.) is lost, so any write + * parameter functions must be called again. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename); + + /* Initialize for writing but indicate that the PDF file should be written to memory. Call + * qpdf_get_buffer_length and qpdf_get_buffer to retrieve the resulting buffer. The memory + * containing the PDF file will be destroyed when qpdf_cleanup is called. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf); + + /* Retrieve the buffer used if the file was written to memory. qpdf_get_buffer returns a null + * pointer if data was not written to memory. The memory is freed when qpdf_cleanup is called + * or if a subsequent call to qpdf_init_write or qpdf_init_write_memory is called. */ + QPDF_DLL + size_t qpdf_get_buffer_length(qpdf_data qpdf); + QPDF_DLL + unsigned char const* qpdf_get_buffer(qpdf_data qpdf); + + QPDF_DLL + void qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode); + + QPDF_DLL + void qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode); + + QPDF_DLL + void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_decode_level(qpdf_data qpdf, enum qpdf_stream_decode_level_e level); + + QPDF_DLL + void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_ID except in test suites to suppress generation of a random /ID. + * See also qpdf_set_deterministic_ID. + */ + QPDF_DLL + void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value); + + /* Never use qpdf_set_static_aes_IV except in test suites to create predictable AES encrypted + * output. + */ + QPDF_DLL + void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_suppress_original_object_IDs(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value); + + /* The *_insecure functions are identical to the old versions but have been renamed as a an + * alert to the caller that they are insecure. See "Weak Cryptographic" in the manual for + * details. + */ + QPDF_DLL + void qpdf_set_r2_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_print, + QPDF_BOOL allow_modify, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_annotate); + + QPDF_DLL + void qpdf_set_r3_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print); + + QPDF_DLL + void qpdf_set_r4_encryption_parameters_insecure( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata, + QPDF_BOOL use_aes); + + QPDF_DLL + void qpdf_set_r5_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_r6_encryption_parameters2( + qpdf_data qpdf, + char const* user_password, + char const* owner_password, + QPDF_BOOL allow_accessibility, + QPDF_BOOL allow_extract, + QPDF_BOOL allow_assemble, + QPDF_BOOL allow_annotate_and_form, + QPDF_BOOL allow_form_filling, + QPDF_BOOL allow_modify_other, + enum qpdf_r3_print_e print, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); + + QPDF_DLL + void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void qpdf_set_minimum_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level); + + QPDF_DLL + void qpdf_force_pdf_version(qpdf_data qpdf, char const* version); + + QPDF_DLL + void + qpdf_force_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level); + + /* During write, your report_progress function will be called with a value between 0 and 100 + * representing the approximate write progress. The data object you pass to + * qpdf_register_progress_reporter will be handed back to your function. This function must be + * called after qpdf_init_write (or qpdf_init_write_memory) and before qpdf_write. The + * registered progress reporter applies only to a single write, so you must call it again if you + * perform a subsequent write with a new writer. + */ + QPDF_DLL + void qpdf_register_progress_reporter( + qpdf_data qpdf, void (*report_progress)(int percent, void* data), void* data); + + /* Do actual write operation. */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf); + + /* Object handling. + * + * These functions take and return a qpdf_oh object handle, which is just an unsigned integer. + * The value 0 is never returned, which makes it usable as an uninitialized value. The handles + * returned by these functions are guaranteed to be unique, i.e. two calls to (the same of + * different) functions will return distinct handles even when they refer to the same object. + * + * Each function below, starting with qpdf_oh, corresponds to a specific method of + * QPDFObjectHandler. For example, qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If + * the C++ method is overloaded, the C function's name will be disambiguated. If the C++ method + * takes optional arguments, the C function will have required arguments in those positions. For + * details about the method, please see comments in QPDFObjectHandle.hh. Comments here only + * explain things that are specific to the "C" API. + * + * Only a fraction of the methods of QPDFObjectHandle are available here. Most of the basic + * methods for creating, accessing, and modifying most types of objects are present. Most of the + * higher-level functions are not implemented. Functions for dealing with content streams as + * well as objects that only exist in content streams (operators and inline images) are mostly + * not provided. + * + * To refer to a specific QPDFObjectHandle, you need a pair consisting of a qpdf_data and a + * qpdf_oh, which is just an index into an internal table of objects. All memory allocated by + * any of these functions is returned when qpdf_cleanup is called. + * + * Regarding memory, the same rules apply as the above functions. Specifically, if a function + * returns a char*, the memory is managed by the library and, unless otherwise specified, is not + * expected to be valid after the next qpdf call. + * + * The qpdf_data object keeps a cache of handles returned by these functions. Once you are + * finished referencing a handle, you can optionally release it. Releasing handles is optional + * since they will all get released by qpdf_cleanup, but it can help to reduce the memory + * footprint of the qpdf_data object to release them when you're done. Releasing a handle does + * not destroy the object. All QPDFObjectHandle objects are deleted when they are no longer + * referenced. Releasing an object handle simply invalidates it. For example, if you create an + * object, add it to an existing dictionary or array, and then release its handle, the object is + * safely part of the dictionary or array. Similarly, any other object handle referring to the + * object remains valid. Explicitly releasing an object handle is essentially the same as + * letting a QPDFObjectHandle go out of scope in the C++ API. + * + * Please see "ERROR HANDLING" above for details on how error conditions are handled. + */ + + /* For examples of using this API, see examples/pdf-c-objects.c */ + + typedef unsigned int qpdf_oh; + + /* Releasing objects -- see comments above. These functions have no equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_oh_release_all(qpdf_data qpdf); + + /* Clone an object handle */ + QPDF_DLL + qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh); + + /* Get trailer and root objects */ + QPDF_DLL + qpdf_oh qpdf_get_trailer(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_get_root(qpdf_data qpdf); + + /* Retrieve and replace indirect objects */ + QPDF_DLL + qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh); + + /* Wrappers around QPDFObjectHandle methods. Be sure to read corresponding comments in + * QPDFObjectHandle.hh to understand what each function does and what kinds of objects it + * applies to. Note that names are to appear in a canonicalized form starting with a leading + * slash and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle.hh + * for details. + */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_dictionary_of_type( + qpdf_data qpdf, qpdf_oh oh, char const* type, char const* subtype); + + QPDF_DLL + enum qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str); + + QPDF_DLL + QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value); + + QPDF_DLL + long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value); + QPDF_DLL + int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value); + QPDF_DLL + unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value); + QPDF_DLL + unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value); + + QPDF_DLL + char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + QPDF_DLL + QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value); + + QPDF_DLL + char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + + /* Return the length of the last string returned. This enables you to retrieve the entire string + * for cases in which a char* returned by one of the functions below points to a string with + * embedded null characters. The function qpdf_oh_get_binary_string_value takes a length + * pointer, which can be useful if you are retrieving the value of a string that is expected to + * contain binary data, such as a checksum or document ID. It is always valid to call + * qpdf_get_last_string_length, but it is usually not necessary as C strings returned by the + * library are only expected to be able to contain null characters if their values originate + * from PDF strings in the input. + */ + QPDF_DLL + size_t qpdf_get_last_string_length(qpdf_data qpdf); + + QPDF_DLL + char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + QPDF_BOOL + qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + QPDF_DLL + char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length); + + QPDF_DLL + int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n); + + /* In all dictionary APIs, keys are specified/represented as canonicalized name strings starting + * with / and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle for + * details. + */ + + /* "C"-specific dictionary key iteration */ + + /* Iteration is allowed on only one dictionary at a time. */ + QPDF_DLL + void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh dict); + QPDF_DLL + QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf); + /* The memory returned by qpdf_oh_dict_next_key is owned by qpdf_data. It is good until the next + * call to qpdf_oh_dict_next_key with the same qpdf_data object. Calling the function again, + * even with a different dict, invalidates previous return values. + */ + QPDF_DLL + char const* qpdf_oh_dict_next_key(qpdf_data qpdf); + + /* end "C"-specific dictionary key iteration */ + + QPDF_DLL + QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + qpdf_oh qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + QPDF_BOOL + qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key); + + QPDF_DLL + qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_null(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value); + QPDF_DLL + qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value); + QPDF_DLL + qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf, double value, int decimal_places); + QPDF_DLL + qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name); + QPDF_DLL + qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str); + QPDF_DLL + qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str); + /* Use qpdf_oh_new_binary_string for creating a string that may contain arbitrary binary data + * including embedded null characters. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* str, size_t length); + QPDF_DLL + qpdf_oh qpdf_oh_new_array(qpdf_data qpdf); + QPDF_DLL + qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf); + + /* Create a new stream. Use qpdf_oh_get_dict to get (and subsequently modify) the stream + * dictionary if needed. See comments in QPDFObjectHandle.hh for newStream() for additional + * notes. You must call qpdf_oh_replace_stream_data to provide data for the stream. See STREAM + * FUNCTIONS below. + */ + QPDF_DLL + qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf); + + QPDF_DLL + void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item); + QPDF_DLL + void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item); + QPDF_DLL + void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at); + + QPDF_DLL + void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + QPDF_DLL + void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key); + QPDF_DLL + void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item); + + QPDF_DLL + qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh); + + QPDF_DLL + char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh); + QPDF_DLL + char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh); + + /* Note about foreign objects: the C API does not have enough information in the value of a + * qpdf_oh to know what QPDF object it belongs to. To uniquely specify a qpdf object handle from + * a specific qpdf_data instance, you always pair the qpdf_oh with the correct qpdf_data. + * Otherwise, you are likely to get completely the wrong object if you are not lucky enough to + * get an error about the object being invalid. + */ + + /* Copy foreign object: the qpdf_oh returned belongs to `qpdf`, while `foreign_oh` belongs to + * `other_qpdf`. + */ + QPDF_DLL + qpdf_oh qpdf_oh_copy_foreign_object(qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh); + + /* STREAM FUNCTIONS */ + + /* These functions provide basic access to streams and stream data. They are not as + * comprehensive as what is in QPDFObjectHandle, but they do allow for working with streams and + * stream data as caller-managed memory. + */ + + /* Get stream data as a buffer. The buffer is allocated with malloc and must be freed by the + * caller. The size of the buffer is stored in *len. The arguments are similar to those in + * QPDFObjectHandle::pipeStreamData. To get raw stream data, pass qpdf_dl_none as decode_level. + * Otherwise, filtering is attempted and *filtered is set to indicate whether it was successful. + * If *filtered is QPDF_FALSE, then raw, unfiltered stream data was returned. You may pass a + * null pointer as filtered if you don't care about the result. If you pass a null pointer as + * bufp (and len), the value of filtered will be set to whether the stream can be filterable. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + enum qpdf_stream_decode_level_e decode_level, + QPDF_BOOL* filtered, + unsigned char** bufp, + size_t* len); + + /* This function returns the concatenation of all of a page's content streams as a single, + * dynamically allocated buffer. As with qpdf_oh_get_stream_data, the buffer is allocated with + * malloc and must be freed by the caller. + */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_oh_get_page_content_data( + qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len); + + /* Call free to release a buffer allocated with malloc. This function can be used to free + * buffers that were dynamically allocated by qpdf functions such as qpdf_oh_get_stream_data or + * qpdf_oh_get_page_content_data. The caller is responsible for calling qpdf_oh_free_buffer (or + * calling free directly) to manage memory properly and avoid memory leaks. This function has no + * equivalent in the C++ API. + */ + QPDF_DLL + void qpdf_oh_free_buffer(unsigned char** bufp); + + /* The data pointed to by bufp will be copied by the library. It does not need to remain valid + * after the call returns. + */ + QPDF_DLL + void qpdf_oh_replace_stream_data( + qpdf_data qpdf, + qpdf_oh stream_oh, + unsigned char const* buf, + size_t len, + qpdf_oh filter, + qpdf_oh decode_parms); + + /* PAGE FUNCTIONS */ + + /* The first time a page function is called, qpdf will traverse the /Pages tree. Subsequent + * calls to retrieve the number of pages or a specific page run in constant time as they are + * accessing the pages cache. If you manipulate the page tree outside of these functions, you + * should call qpdf_update_all_pages_cache. See comments for getAllPages() and + * updateAllPagesCache() in QPDF.hh. + */ + + /* For each function, the corresponding method in QPDF.hh is referenced. Please see comments in + * QPDF.hh for details. + */ + + /* calls getAllPages(). On error, returns -1 and sets error for qpdf_get_error. */ + QPDF_DLL + int qpdf_get_num_pages(qpdf_data qpdf); + /* returns uninitialized object if out of range */ + QPDF_DLL + qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index); + + /* updateAllPagesCache() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf); + + /* findPage() -- return zero-based index. If page is not found, return -1 and save the error to + * be retrieved with qpdf_get_error. + */ + QPDF_DLL + int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation); + QPDF_DLL + int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh); + + /* pushInheritedAttributesToPage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf); + + /* Functions that add pages may add pages from other files. If adding a page from the same file, + newpage_qpdf and qpdf are the same. + */ + + /* addPage() */ + QPDF_DLL + QPDF_ERROR_CODE + qpdf_add_page(qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first); + /* addPageAt() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_add_page_at( + qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL before, qpdf_oh refpage); + /* removePage() */ + QPDF_DLL + QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page); + + /* GLOBAL OPTIONS AND SETTINGS */ + + QPDF_DLL + /** + * @brief Retrieves a 32-bit unsigned integer value associated with a global option or limit. + * + * This function allows querying of specific parameters, identified by the qpdf_param_e enum, + * and retrieves their associated unsigned 32-bit integer values. The result will be stored in + * the variable pointed to by `value`. For details about the available parameters and their + * meanings see `qpdf/global.hh`. + * + * @param param[in] The parameter for which the value is being retrieved. This must be a valid + * value from the qpdf_param_e enumeration. + * @param value[out] A pointer to a uint32_t to store the retrieved value. This must be a valid, + * non-null pointer. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_get_uint32(enum qpdf_param_e param, uint32_t* value); + + QPDF_DLL + /** + * @brief Sets a global option or limit for the qpdf library to a specified value. + * + * This function is used to configure global options or limits for the qpdf library based on the + * provided parameter and value. The behavior depends on the specific `param` provided and its + * valid range of values. For details about the available parameters and their meanings see + * `qpdf/global.hh`. + * + * @param param[in] The parameter to be set. Must be one of the values defined in the + * qpdf_param_e enumeration. + * @param value[in] The value to assign to the specified parameter. Interpretation of this value + * depends on the parameter being set. + * + * @return An enumeration of type qpdf_result_e indicating the result of the operation. Possible + * values include success or specific error statuses related to the retrieval process. + * + * @since 12.3 + */ + enum qpdf_result_e qpdf_global_set_uint32(enum qpdf_param_e param, uint32_t value); +#ifdef __cplusplus +} + +// These C++ functions make it easier to write C++ code that interoperates with the C API. +// See examples/extend-c-api. + +# include +# include + +# include + +// Retrieve the real QPDF object attached to this qpdf_data. +QPDF_DLL +std::shared_ptr qpdf_c_get_qpdf(qpdf_data qpdf); + +// Wrap a C++ function that may throw an exception to translate the exception for retrieval using +// the normal QPDF C API methods. +QPDF_DLL +QPDF_ERROR_CODE qpdf_c_wrap(qpdf_data qpdf, std::function fn); +#endif + +#endif /* QPDF_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdfjob-c.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdfjob-c.h new file mode 100644 index 0000000..a00b923 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdfjob-c.h @@ -0,0 +1,156 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFJOB_C_H +#define QPDFJOB_C_H + +/* + * This file defines a basic "C" API for QPDFJob. See also qpdf-c.h, which defines an API that + * exposes more of the library's API. This API is primarily intended to make it simpler for programs + * in languages other than C++ to incorporate functionality that could be run directly from the + * command-line. + */ + +#include +#include +#include +#include +#ifndef QPDF_NO_WCHAR_T +# include +#endif + +/* + * This file provides a minimal wrapper around QPDFJob. See examples/qpdfjob-c.c for an example of + * its use. + */ + +#ifdef __cplusplus +extern "C" { +#endif + /* SHORT INTERFACE -- These functions are single calls that take care of the whole life cycle of + * QPDFJob. They can be used for one-shot operations where no additional configuration is + * needed. See FULL INTERFACE below. */ + + /* This function does the equivalent of running the qpdf command-line with the given arguments + * and returns the exit code that qpdf would use. argv must be a null-terminated array of + * null-terminated UTF8-encoded strings. If calling this from wmain on Windows, use + * qpdfjob_run_from_wide_argv instead. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_argv(char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_run_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_run_from_wide_argv(wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function runs QPDFJob from a job JSON file. See the "QPDF Job" section of the manual for + * details. The JSON string must be UTF8-encoded. It returns the error code that qpdf would + * return with the equivalent command-line invocation. Exit code values are defined in + * Constants.h in the qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run_from_json(char const* json); + + /* FULL INTERFACE -- new in qpdf11. Similar to the qpdf-c.h API, you must call qpdfjob_init to + * get a qpdfjob_handle and, when done, call qpdfjob_cleanup to free resources. Remaining + * methods take qpdfjob_handle as an argument. This interface requires more calls but also + * offers greater flexibility. + */ + typedef struct _qpdfjob_handle* qpdfjob_handle; + QPDF_DLL + qpdfjob_handle qpdfjob_init(); + + QPDF_DLL + void qpdfjob_cleanup(qpdfjob_handle* j); + + /* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when + * you are done with the handles. The underlying logger is cleaned up automatically and persists + * if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details. + */ + + QPDF_DLL + void qpdfjob_set_logger(qpdfjob_handle j, qpdflogger_handle logger); + QPDF_DLL + qpdflogger_handle qpdfjob_get_logger(qpdfjob_handle j); + + /* This function wraps QPDFJob::initializeFromArgv. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]); + +#ifndef QPDF_NO_WCHAR_T + /* This function is the same as qpdfjob_initialize_from_argv except argv is encoded with wide + * characters. This would be suitable for calling from a Windows wmain function. + */ + QPDF_DLL + int qpdfjob_initialize_from_wide_argv(qpdfjob_handle j, wchar_t const* const argv[]); +#endif /* QPDF_NO_WCHAR_T */ + + /* This function wraps QPDFJob::initializeFromJson. The return value is the same as qpdfjob_run. + * If this returns an error, it is invalid to call any other functions using this job handle. + */ + QPDF_DLL + int qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json); + + /* This function wraps QPDFJob::run. It returns the error code that qpdf would return with the + * equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. + */ + QPDF_DLL + int qpdfjob_run(qpdfjob_handle j); + + /* The following two functions allow a job to be run in two stages - creation of a qpdf_data + * object and writing of the qpdf_data object. This allows the qpdf_data object to be modified + * prior to writing it out. See examples/qpdfjob-remove-annotations for a C++ illustration of + * its use. + * + * This function wraps QPDFJob::createQPDF. It runs the first stage of the job. A nullptr is + * returned if the job did not produce any pdf file to be written. + */ + QPDF_DLL + qpdf_data qpdfjob_create_qpdf(qpdfjob_handle j); + + /* This function wraps QPDFJob::writeQPDF. It returns the error code that qpdf would return with + * the equivalent command-line invocation. Exit code values are defined in Constants.h in the + * qpdf_exit_code_e type. NOTE it is the callers responsibility to clean up the resources + * associated with the qpdf_data object by calling qpdf_cleanup after the call to + * qpdfjob_write_qpdf. + */ + QPDF_DLL + int qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf); + + /* Allow specification of a custom progress reporter. The progress reporter is only used if + * progress is otherwise requested (with the --progress option or "progress": "" in the JSON). + */ + QPDF_DLL + void qpdfjob_register_progress_reporter( + qpdfjob_handle j, void (*report_progress)(int percent, void* data), void* data); + +#ifdef __cplusplus +} +#endif + +#endif /* QPDFJOB_C_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdflogger-c.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdflogger-c.h new file mode 100644 index 0000000..b3d706a --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/qpdf/qpdflogger-c.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2005-2021 Jay Berkenbilt + * Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger + * + * This file is part of qpdf. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * Versions of qpdf prior to version 7 were released under the terms of version 2.0 of the Artistic + * License. At your option, you may continue to consider qpdf to be licensed under those terms. + * Please see the manual for additional information. + */ + +#ifndef QPDFLOGGER_H +#define QPDFLOGGER_H + +/* + * This file provides a C API for QPDFLogger. See QPDFLogger.hh for information about the logger and + * examples/qpdfjob-c-save-attachment.c for an example. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /* To operate on a logger, you need a handle to it. call qpdflogger_default_logger to get a + * handle for the default logger. There are functions in qpdf-c.h and qpdfjob-c.h that also take + * or return logger handles. When you're done with the logger handler, call qpdflogger_cleanup. + * This cleans up the handle but leaves the underlying log object intact. (It uses a shared + * pointer and will be cleaned up automatically when it is no longer in use.) That means you can + * create a logger with qpdflogger_create(), pass the logger handle to a function in qpdf-c.h or + * qpdfjob-c.h, and then clean it up, subject to constraints imposed by the other function. + */ + + typedef struct _qpdflogger_handle* qpdflogger_handle; + QPDF_DLL + qpdflogger_handle qpdflogger_default_logger(); + + /* Calling cleanup on the handle returned by qpdflogger_create destroys the handle but not the + * underlying logger. See comments above. + */ + QPDF_DLL + qpdflogger_handle qpdflogger_create(); + + QPDF_DLL + void qpdflogger_cleanup(qpdflogger_handle* l); + + enum qpdf_log_dest_e { + qpdf_log_dest_default = 0, + qpdf_log_dest_stdout = 1, + qpdf_log_dest_stderr = 2, + qpdf_log_dest_discard = 3, + qpdf_log_dest_custom = 4, + }; + + /* Function should return 0 on success. */ + typedef int (*qpdf_log_fn_t)(char const* data, size_t len, void* udata); + + QPDF_DLL + void qpdflogger_set_info( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_warn( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + QPDF_DLL + void qpdflogger_set_error( + qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata); + + /* A non-zero value for only_if_not_set means that the save pipeline will only be changed if it + * is not already set. + */ + QPDF_DLL + void qpdflogger_set_save( + qpdflogger_handle l, + enum qpdf_log_dest_e dest, + qpdf_log_fn_t fn, + void* udata, + int only_if_not_set); + QPDF_DLL + void qpdflogger_save_to_standard_output(qpdflogger_handle l, int only_if_not_set); + + /* For testing */ + QPDF_DLL + int qpdflogger_equal(qpdflogger_handle l1, qpdflogger_handle l2); + +#ifdef __cplusplus +} +#endif + +#endif // QPDFLOGGER_H diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/turbojpeg.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/turbojpeg.h new file mode 100644 index 0000000..9255aee --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/turbojpeg.h @@ -0,0 +1,2923 @@ +/* + * Copyright (C) 2009-2015, 2017, 2020-2026 D. R. Commander + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the libjpeg-turbo Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TURBOJPEG_H__ +#define __TURBOJPEG_H__ + +#include + +#define TURBOJPEG_VERSION_NUMBER 3002000 + +#if defined(_WIN32) && defined(DLLDEFINE) +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif +#define DLLCALL + + +/** + * @addtogroup TurboJPEG + * TurboJPEG API. This API provides an interface for generating, decoding, and + * transforming planar YUV and JPEG images in memory. + * + * @anchor YUVnotes + * YUV Image Format Notes + * ---------------------- + * Technically, the JPEG format uses the YCbCr colorspace (which is technically + * not a colorspace but a color transform), but per the convention of the + * digital video community, the TurboJPEG API uses "YUV" to refer to an image + * format consisting of Y, Cb, and Cr image planes. + * + * Each plane is simply a 2D array of bytes, each byte representing the value + * of one of the components (Y, Cb, or Cr) at a particular location in the + * image. The width and height of each plane are determined by the image + * width, height, and level of chrominance subsampling. The luminance plane + * width is the image width padded to the nearest multiple of the horizontal + * subsampling factor (1 in the case of 4:4:4, grayscale, 4:4:0, or 4:4:1; 2 in + * the case of 4:2:2, 4:2:0, or 2:4; 4 in the case of 4:1:1 or 4:1:0.) + * Similarly, the luminance plane height is the image height padded to the + * nearest multiple of the vertical subsampling factor (1 in the case of 4:4:4, + * 4:2:2, grayscale, or 4:1:1; 2 in the case of 4:2:0, 4:4:0, or 4:1:0; 4 in + * the case of 4:4:1 or 2:4.) This is irrespective of any additional padding + * that may be specified as an argument to the various YUV functions. The + * chrominance plane width is equal to the luminance plane width divided by the + * horizontal subsampling factor, and the chrominance plane height is equal to + * the luminance plane height divided by the vertical subsampling factor. + * + * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is + * used, then the luminance plane would be 36 x 35 bytes, and each of the + * chrominance planes would be 18 x 35 bytes. If you specify a row alignment + * of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, + * and each of the chrominance planes would be 20 x 35 bytes. + * + * @{ + */ + + +/** + * The number of initialization options + */ +#define TJ_NUMINIT 3 + +/** + * Initialization options + */ +enum TJINIT { + /** + * Initialize the TurboJPEG instance for compression. + */ + TJINIT_COMPRESS, + /** + * Initialize the TurboJPEG instance for decompression. + */ + TJINIT_DECOMPRESS, + /** + * Initialize the TurboJPEG instance for lossless transformation (both + * compression and decompression.) + */ + TJINIT_TRANSFORM +}; + + +/** + * The number of chrominance subsampling options + */ +#define TJ_NUMSAMP 9 + +/** + * Chrominance subsampling options + * + * When pixels are converted from RGB to YCbCr (see #TJCS_YCbCr) or from CMYK + * to YCCK (see #TJCS_YCCK) as part of the JPEG compression process, some of + * the Cb and Cr (chrominance) components can be discarded or averaged together + * to produce a smaller image with little perceptible loss of image quality. + * (The human eye is more sensitive to small changes in brightness than to + * small changes in color.) This is called "chrominance subsampling". + */ +enum TJSAMP { + /** + * 4:4:4 chrominance subsampling (no chrominance subsampling) + * + * The JPEG or YUV image will contain one chrominance component for every + * pixel in the source image. + */ + TJSAMP_444, + /** + * 4:2:2 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x1 + * block of pixels in the source image. + */ + TJSAMP_422, + /** + * 4:2:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x2 + * block of pixels in the source image. + */ + TJSAMP_420, + /** + * Grayscale + * + * The JPEG or YUV image will contain no chrominance components. + */ + TJSAMP_GRAY, + /** + * 4:4:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x2 + * block of pixels in the source image. + * + * @note 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_440, + /** + * 4:1:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x1 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:1:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:1:1 is + * better able to reproduce sharp horizontal features. + * + * @note 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_411, + /** + * 4:4:1 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 1x4 + * block of pixels in the source image. All else being equal, a JPEG image + * with 4:4:1 subsampling is almost exactly the same size as a JPEG image + * with 4:2:0 subsampling, and in the aggregate, both subsampling methods + * produce approximately the same perceptual quality. However, 4:4:1 is + * better able to reproduce sharp vertical features. + * + * @note 4:4:1 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_441, + /** + * 4:1:0 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 4x2 + * block of pixels in the source image. 4:1:0 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 4:1:0 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_410, + /** + * 2:4 chrominance subsampling + * + * The JPEG or YUV image will contain one chrominance component for every 2x4 + * block of pixels in the source image. 2:4 chrominance subsampling cannot + * be used with YCCK JPEG images. + * + * @note 2:4 subsampling is not fully accelerated in libjpeg-turbo. + */ + TJSAMP_24, + /** + * Unknown subsampling + * + * The JPEG image uses an unusual type of chrominance subsampling. Such + * images can be decompressed into packed-pixel images, but they cannot be + * - decompressed into planar YUV images, + * - losslessly transformed if #TJXOPT_CROP is specified and #TJXOPT_GRAY is + * not specified, or + * - partially decompressed using a cropping region. + */ + TJSAMP_UNKNOWN = -1 +}; + +/** + * iMCU width (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUWidth[TJ_NUMSAMP] = { 8, 16, 16, 8, 8, 32, 8, 32, 16 }; + +/** + * iMCU height (in pixels) for a given level of chrominance subsampling + * + * In a typical lossy JPEG image, 8x8 blocks of DCT coefficients for each + * component are interleaved in a single scan. If the image uses chrominance + * subsampling, then multiple luminance blocks are stored together, followed by + * a single block for each chrominance component. The minimum set of + * full-resolution luminance block(s) and corresponding (possibly subsampled) + * chrominance blocks necessary to represent at least one DCT block per + * component is called a "Minimum Coded Unit" or "MCU". (For example, an MCU + * in an interleaved lossy JPEG image that uses 4:2:2 subsampling consists of + * two luminance blocks followed by one block for each chrominance component.) + * In a non-interleaved lossy JPEG image, each component is stored in a + * separate scan, and an MCU is a single DCT block, so we use the term "iMCU" + * (interleaved MCU) to refer to the equivalent of an MCU in an interleaved + * JPEG image. For the common case of interleaved JPEG images, an iMCU is the + * same as an MCU. + * + * iMCU sizes: + * - 8x8 for no subsampling or grayscale + * - 16x8 for 4:2:2 + * - 8x16 for 4:4:0 + * - 16x16 for 4:2:0 + * - 32x8 for 4:1:1 + * - 8x32 for 4:4:1 + * - 32x16 for 4:1:0 + * - 16x32 for 2:4 + */ +static const int tjMCUHeight[TJ_NUMSAMP] = { 8, 8, 16, 8, 16, 8, 32, 16, 32 }; + + +/** + * The number of pixel formats + */ +#define TJ_NUMPF 12 + +/** + * Pixel formats + */ +enum TJPF { + /** + * RGB pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. + */ + TJPF_RGB, + /** + * BGR pixel format + * + * The red, green, and blue components in the image are stored in 3-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. + */ + TJPF_BGR, + /** + * RGBX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_RGBX, + /** + * BGRX pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from lowest to highest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_BGRX, + /** + * XBGR pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order R, G, B from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XBGR, + /** + * XRGB pixel format + * + * The red, green, and blue components in the image are stored in 4-sample + * pixels in the order B, G, R from highest to lowest memory address within + * each pixel. The X component is ignored when compressing/encoding and + * undefined when decompressing/decoding. + */ + TJPF_XRGB, + /** + * Grayscale pixel format + * + * Each 1-sample pixel represents a luminance (brightness) level from 0 to + * the maximum sample value (which is, for instance, 255 for 8-bit samples or + * 4095 for 12-bit samples or 65535 for 16-bit samples.) + */ + TJPF_GRAY, + /** + * RGBA pixel format + * + * This is the same as @ref TJPF_RGBX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_RGBA, + /** + * BGRA pixel format + * + * This is the same as @ref TJPF_BGRX, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_BGRA, + /** + * ABGR pixel format + * + * This is the same as @ref TJPF_XBGR, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ABGR, + /** + * ARGB pixel format + * + * This is the same as @ref TJPF_XRGB, except that when + * decompressing/decoding, the X component is guaranteed to be equal to the + * maximum sample value, which can be interpreted as an opaque alpha channel. + */ + TJPF_ARGB, + /** + * CMYK pixel format + * + * Unlike RGB, which is an additive color model used primarily for display, + * CMYK (Cyan/Magenta/Yellow/Key) is a subtractive color model used primarily + * for printing. In the CMYK color model, the value of each color component + * typically corresponds to an amount of cyan, magenta, yellow, or black ink + * that is applied to a white background. In order to convert between CMYK + * and RGB, it is necessary to use a color management system (CMS.) A CMS + * will attempt to map colors within the printer's gamut to perceptually + * similar colors in the display's gamut and vice versa, but the mapping is + * typically not 1:1 or reversible, nor can it be defined with a simple + * formula. Thus, such a conversion is out of scope for a codec library. + * However, the TurboJPEG API allows for compressing packed-pixel CMYK images + * into YCCK JPEG images (see #TJCS_YCCK) and decompressing YCCK JPEG images + * into packed-pixel CMYK images. + */ + TJPF_CMYK, + /** + * Unknown pixel format + * + * Currently this is only used by #tj3LoadImage8(), #tj3LoadImage12(), and + * #tj3LoadImage16(). + */ + TJPF_UNKNOWN = -1 +}; + +/** + * Red offset (in samples) for a given pixel format + * + * This specifies the number of samples that the red component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the red + * component is `pixel[tjRedOffset[TJPF_BGRX]]`. The offset is -1 if the pixel + * format does not have a red component. + */ +static const int tjRedOffset[TJ_NUMPF] = { + 0, 2, 0, 2, 3, 1, -1, 0, 2, 3, 1, -1 +}; +/** + * Green offset (in samples) for a given pixel format + * + * This specifies the number of samples that the green component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the green + * component is `pixel[tjGreenOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a green component. + */ +static const int tjGreenOffset[TJ_NUMPF] = { + 1, 1, 1, 1, 2, 2, -1, 1, 1, 2, 2, -1 +}; +/** + * Blue offset (in samples) for a given pixel format + * + * This specifies the number of samples that the blue component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRX is stored in `unsigned char pixel[]`, then the blue + * component is `pixel[tjBlueOffset[TJPF_BGRX]]`. The offset is -1 if the + * pixel format does not have a blue component. + */ +static const int tjBlueOffset[TJ_NUMPF] = { + 2, 0, 2, 0, 1, 3, -1, 2, 0, 1, 3, -1 +}; +/** + * Alpha offset (in samples) for a given pixel format + * + * This specifies the number of samples that the alpha component is offset from + * the start of the pixel. For instance, if an 8-bit-per-component pixel of + * format TJPF_BGRA is stored in `unsigned char pixel[]`, then the alpha + * component is `pixel[tjAlphaOffset[TJPF_BGRA]]`. The offset is -1 if the + * pixel format does not have an alpha component. + */ +static const int tjAlphaOffset[TJ_NUMPF] = { + -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 +}; +/** + * Pixel size (in samples) for a given pixel format + */ +static const int tjPixelSize[TJ_NUMPF] = { + 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4 +}; + + +/** + * The number of JPEG colorspaces + */ +#define TJ_NUMCS 5 + +/** + * JPEG colorspaces + */ +enum TJCS { + /** + * RGB colorspace + * + * When generating the JPEG image, the R, G, and B components in the source + * image are reordered into image planes, but no colorspace conversion or + * subsampling is performed. RGB JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats, but they cannot be generated from or + * decompressed to planar YUV images. + */ + TJCS_RGB, + /** + * YCbCr colorspace + * + * YCbCr is not an absolute colorspace but rather a mathematical + * transformation of RGB designed solely for storage and transmission. YCbCr + * images must be converted to RGB before they can be displayed. In the + * YCbCr colorspace, the Y (luminance) component represents the black & white + * portion of the original image, and the Cb and Cr (chrominance) components + * represent the color portion of the original image. Historically, the + * analog equivalent of this transformation allowed the same signal to be + * displayed to both black & white and color televisions, but JPEG images + * primarily use YCbCr because it optionally allows the color data to be + * subsampled in order to reduce network and disk usage. YCbCr is the most + * common JPEG colorspace, and YCbCr JPEG images can be generated from and + * decompressed to packed-pixel images with any of the extended RGB or + * grayscale pixel formats. YCbCr JPEG images can also be generated from + * and decompressed to planar YUV images. + */ + TJCS_YCbCr, + /** + * Grayscale colorspace + * + * The JPEG image retains only the luminance data (Y component), and any + * color data from the source image is discarded. Grayscale JPEG images can + * be generated from and decompressed to packed-pixel images with any of the + * extended RGB or grayscale pixel formats, or they can be generated from + * and decompressed to planar YUV images. + */ + TJCS_GRAY, + /** + * CMYK colorspace + * + * When generating the JPEG image, the C, M, Y, and K components in the + * source image are reordered into image planes, but no colorspace conversion + * or subsampling is performed. CMYK JPEG images can only be generated from + * and decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_CMYK, + /** + * YCCK colorspace + * + * YCCK (AKA "YCbCrK") is not an absolute colorspace but rather a + * mathematical transformation of CMYK designed solely for storage and + * transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + * reversibly transformed into YCCK, and as with YCbCr, the chrominance + * components in the YCCK pixels can be subsampled without incurring major + * perceptual loss. YCCK JPEG images can only be generated from and + * decompressed to packed-pixel images with the CMYK pixel format. + */ + TJCS_YCCK, + /** + * Default colorspace + * + * Generate a grayscale JPEG image if #TJPARAM_SUBSAMP is set to + * #TJSAMP_GRAY, a YCCK JPEG image if the source image is CMYK, and a YCbCr + * JPEG image otherwise. + */ + TJCS_DEFAULT = -1 +}; + + +/** + * Parameters + */ +enum TJPARAM { + /** + * Error handling behavior + * + * **Value** + * - `0` *[default]* Allow the current compression/decompression/transform + * operation to complete unless a fatal error is encountered. + * - `1` Immediately discontinue the current + * compression/decompression/transform operation if a warning (non-fatal + * error) occurs. + */ + TJPARAM_STOPONWARNING, + /** + * Row order in packed-pixel source/destination images + * + * **Value** + * - `0` *[default]* top-down (X11) order + * - `1` bottom-up (Windows, OpenGL) order + */ + TJPARAM_BOTTOMUP, + /** + * JPEG destination buffer (re)allocation [compression, lossless + * transformation] + * + * **Value** + * - `0` *[default]* Attempt to allocate or reallocate the JPEG destination + * buffer as needed. + * - `1` Generate an error if the JPEG destination buffer is invalid or too + * small. + */ + TJPARAM_NOREALLOC, + /** + * Perceptual quality of lossy JPEG images [compression only] + * + * **Value** + * - `1`-`100` (`1` = worst quality but best compression, `100` = best + * quality but worst compression) *[no default; must be explicitly + * specified]* + */ + TJPARAM_QUALITY, + /** + * Chrominance subsampling level + * + * The JPEG or YUV image uses (decompression, decoding) or will use (lossy + * compression, encoding) the specified level of chrominance subsampling. + * + * **Value** + * - One of the @ref TJSAMP "chrominance subsampling options" *[no default; + * must be explicitly specified for lossy compression, encoding, and + * decoding]* + */ + TJPARAM_SUBSAMP, + /** + * JPEG width (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGWIDTH, + /** + * JPEG height (in pixels) [decompression only, read-only] + */ + TJPARAM_JPEGHEIGHT, + /** + * Data precision (bits per sample) + * + * The JPEG image uses (decompression) or will use (lossless compression) the + * specified number of bits per sample. This parameter also specifies the + * target data precision when loading a PNG or PBMPLUS file with + * #tj3LoadImage8(), #tj3LoadImage12(), or #tj3LoadImage16() and the source + * data precision when saving a PNG or PBMPLUS file with #tj3SaveImage8(), + * #tj3SaveImage12(), or #tj3SaveImage16(). + * + * The data precision is the number of bits in the maximum sample value, + * which may not be the same as the width of the data type used to store the + * sample. + * + * **Value** + * - `8` or `12` for lossy JPEG images; `2` to `16` for lossless JPEG, PNG, + * and PBMPLUS images + * + * 12-bit JPEG data precision implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is set. + */ + TJPARAM_PRECISION, + /** + * JPEG colorspace + * + * The JPEG image uses (decompression) or will use (lossy compression) the + * specified colorspace. + * + * **Value** + * - One of the @ref TJCS "JPEG colorspaces" *[default for lossy compression: + * automatically selected based on the subsampling level and pixel format]* + */ + TJPARAM_COLORSPACE, + /** + * Chrominance upsampling algorithm [lossy decompression only] + * + * **Value** + * - `0` *[default]* Use smooth upsampling when decompressing a JPEG image + * that was generated using 4:2:2, 4:2:0, or 4:4:0 chrominance subsampling. + * This creates a smooth transition between neighboring chrominance + * components in order to reduce upsampling artifacts in the decompressed + * image. + * - `1` Use the fastest chrominance upsampling algorithm available, which + * may combine upsampling with color conversion. + */ + TJPARAM_FASTUPSAMPLE, + /** + * DCT/IDCT algorithm [lossy compression and decompression] + * + * **Value** + * - `0` *[default]* Use the most accurate DCT/IDCT algorithm available. + * - `1` Use the fastest DCT/IDCT algorithm available. + * + * This parameter is provided mainly for backward compatibility with libjpeg, + * which historically implemented several different DCT/IDCT algorithms + * because of performance limitations with 1990s CPUs. In the libjpeg-turbo + * implementation of the TurboJPEG API: + * - The "fast" and "accurate" DCT/IDCT algorithms perform similarly on + * modern x86/x86-64 CPUs that support AVX2 instructions. + * - The "fast" algorithm is generally only about 5-15% faster than the + * "accurate" algorithm on other types of CPUs. + * - The difference in accuracy between the "fast" and "accurate" algorithms + * is the most pronounced at JPEG quality levels above 90 and tends to be + * more pronounced with decompression than with compression. + * - For JPEG quality levels above 97, the "fast" algorithm degrades and is + * not fully accelerated, so it is slower than the "accurate" algorithm. + */ + TJPARAM_FASTDCT, + /** + * Huffman table optimization [lossy compression, lossless transformation] + * + * **Value** + * - `0` *[default]* The JPEG image will use the default Huffman tables. + * - `1` Optimal Huffman tables will be computed for the JPEG image. For + * lossless transformation, this can also be specified using + * #TJXOPT_OPTIMIZE. + * + * Huffman table optimization improves compression slightly (generally 5% or + * less), but it reduces compression performance considerably. + */ + TJPARAM_OPTIMIZE, + /** + * Progressive JPEG + * + * In a progressive JPEG image, the DCT coefficients are split across + * multiple "scans" of increasing quality. Thus, a low-quality scan + * containing the lowest-frequency DCT coefficients can be transmitted first + * and refined with subsequent higher-quality scans containing + * higher-frequency DCT coefficients. When using Huffman entropy coding, the + * progressive JPEG format also provides an "end-of-bands (EOB) run" feature + * that allows large groups of zeroes, potentially spanning multiple MCUs, + * to be represented using only a few bytes. + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image is (decompression) or will be (compression, lossless transformation) + * single-scan. + * - `1` The lossy JPEG image is (decompression) or will be (compression, + * lossless transformation) progressive. For lossless transformation, this + * can also be specified using #TJXOPT_PROGRESSIVE. + * + * Progressive JPEG images generally have better compression ratios than + * single-scan JPEG images (much better if the image has large areas of solid + * color), but progressive JPEG compression and decompression is considerably + * slower than single-scan JPEG compression and decompression. Can be + * combined with #TJPARAM_ARITHMETIC. Implies #TJPARAM_OPTIMIZE unless + * #TJPARAM_ARITHMETIC is also set. + */ + TJPARAM_PROGRESSIVE, + /** + * Progressive JPEG scan limit for lossy JPEG images [decompression, lossless + * transformation] + * + * Setting this parameter causes the decompression and transform functions to + * return an error if the number of scans in a progressive JPEG image exceeds + * the specified limit. The primary purpose of this is to allow + * security-critical applications to guard against an exploit of the + * progressive JPEG format described in + * this report. + * + * **Value** + * - maximum number of progressive JPEG scans that the decompression and + * transform functions will process *[default: `0` (no limit)]* + * + * @see #TJPARAM_PROGRESSIVE + */ + TJPARAM_SCANLIMIT, + /** + * Arithmetic entropy coding + * + * **Value** + * - `0` *[default for compression, lossless transformation]* The lossy JPEG + * image uses (decompression) or will use (compression, lossless + * transformation) Huffman entropy coding. + * - `1` The lossy JPEG image uses (decompression) or will use (compression, + * lossless transformation) arithmetic entropy coding. For lossless + * transformation, this can also be specified using #TJXOPT_ARITHMETIC. + * + * Arithmetic entropy coding generally improves compression relative to + * Huffman entropy coding, but it reduces compression and decompression + * performance considerably. Can be combined with #TJPARAM_PROGRESSIVE. + */ + TJPARAM_ARITHMETIC, + /** + * Lossless JPEG + * + * **Value** + * - `0` *[default for compression]* The JPEG image is (decompression) or + * will be (compression) lossy/DCT-based. + * - `1` The JPEG image is (decompression) or will be (compression) + * lossless/predictive. + * + * In most cases, lossless JPEG compression and decompression is considerably + * slower than lossy JPEG compression and decompression, and lossless JPEG + * images are much larger than lossy JPEG images. Thus, lossless JPEG images + * are typically used only for applications that require mathematically + * lossless compression. Also note that the following features are not + * available with lossless JPEG images: + * - Colorspace conversion (lossless JPEG images always use #TJCS_RGB, + * #TJCS_GRAY, or #TJCS_CMYK, depending on the pixel format of the source + * image) + * - Chrominance subsampling (lossless JPEG images always use #TJSAMP_444) + * - JPEG quality selection + * - DCT/IDCT algorithm selection + * - Progressive JPEG + * - Arithmetic entropy coding + * - Compression from/decompression to planar YUV images (this parameter is + * ignored by #tj3CompressFromYUV8() and #tj3CompressFromYUVPlanes8()) + * - Decompression scaling + * - Lossless transformation + * + * @see #TJPARAM_LOSSLESSPSV, #TJPARAM_LOSSLESSPT + */ + TJPARAM_LOSSLESS, + /** + * Lossless JPEG predictor selection value (PSV) + * + * **Value** + * - `1`-`7` *[default for compression: `1`]* + * + * Lossless JPEG compression shares no algorithms with lossy JPEG + * compression. Instead, it uses differential pulse-code modulation (DPCM), + * an algorithm whereby each sample is encoded as the difference between the + * sample's value and a "predictor", which is based on the values of + * neighboring samples. If Ra is the sample immediately to the left of the + * current sample, Rb is the sample immediately above the current sample, and + * Rc is the sample diagonally to the left and above the current sample, then + * the relationship between the predictor selection value and the predictor + * is as follows: + * + * PSV | Predictor + * ----|---------- + * 1 | Ra + * 2 | Rb + * 3 | Rc + * 4 | Ra + Rb – Rc + * 5 | Ra + (Rb – Rc) / 2 + * 6 | Rb + (Ra – Rc) / 2 + * 7 | (Ra + Rb) / 2 + * + * Predictors 1-3 are 1-dimensional predictors, whereas Predictors 4-7 are + * 2-dimensional predictors. The best predictor for a particular image + * depends on the image. + * + * @see #TJPARAM_LOSSLESS + */ + TJPARAM_LOSSLESSPSV, + /** + * Lossless JPEG point transform (Pt) + * + * **Value** + * - `0` through ***precision*** *- 1*, where ***precision*** is the JPEG + * data precision in bits *[default for compression: `0`]* + * + * A point transform value of `0` is necessary in order to generate a fully + * lossless JPEG image. (A non-zero point transform value right-shifts the + * input samples by the specified number of bits, which is effectively a form + * of lossy color quantization.) + * + * @see #TJPARAM_LOSSLESS, #TJPARAM_PRECISION + */ + TJPARAM_LOSSLESSPT, + /** + * JPEG restart marker interval in MCUs [lossy compression, + * lossless transformation] + * + * The nature of entropy coding is such that a corrupt JPEG image cannot + * be decompressed beyond the point of corruption unless it contains restart + * markers. A restart marker stops and restarts the entropy coding algorithm + * so that, if a JPEG image is corrupted, decompression can resume at the + * next marker. Thus, adding more restart markers improves the fault + * tolerance of the JPEG image, but adding too many restart markers can + * adversely affect the compression ratio and performance. + * + * In typical JPEG images, an MCU (Minimum Coded Unit) is the minimum set of + * interleaved "data units" (8x8 DCT blocks if the image is lossy or samples + * if the image is lossless) necessary to represent at least one data unit + * per component. (For example, an MCU in an interleaved lossy JPEG image + * that uses 4:2:2 subsampling consists of two luminance blocks followed by + * one block for each chrominance component.) In single-component or + * non-interleaved JPEG images, an MCU is the same as a data unit. + * + * **Value** + * - the number of MCUs between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTROWS to 0. + */ + TJPARAM_RESTARTBLOCKS, + /** + * JPEG restart marker interval in MCU rows [compression, + * lossless transformation] + * + * See #TJPARAM_RESTARTBLOCKS for a description of restart markers and MCUs. + * An MCU row is a row of MCUs spanning the entire width of the image. + * + * **Value** + * - the number of MCU rows between each restart marker *[default: `0` (no + * restart markers)]* + * + * Setting this parameter to a non-zero value sets #TJPARAM_RESTARTBLOCKS to + * 0. + */ + TJPARAM_RESTARTROWS, + /** + * JPEG horizontal pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified horizontal pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_XDENSITY, + /** + * JPEG vertical pixel density + * + * **Value** + * - The JPEG image has (decompression) or will have (compression) the + * specified vertical pixel density *[default for compression: `1`]*. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value of #TJPARAM_DENSITYUNITS + * is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_DENSITYUNITS + */ + TJPARAM_YDENSITY, + /** + * JPEG pixel density units + * + * **Value** + * - `0` *[default for compression]* The pixel density of the JPEG image is + * expressed (decompression) or will be expressed (compression) in unknown + * units. + * - `1` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/inch. + * - `2` The pixel density of the JPEG image is expressed (decompression) or + * will be expressed (compression) in units of pixels/cm. + * + * This value is stored in or read from the JPEG header. It does not affect + * the contents of the JPEG image. Note that this parameter is set by + * #tj3LoadImage8() when loading a Windows BMP file that contains pixel + * density information, and the value of this parameter is stored to a + * Windows BMP file by #tj3SaveImage8() if the value is `2`. + * + * This parameter has no effect unless the JPEG colorspace (see + * #TJPARAM_COLORSPACE) is #TJCS_YCbCr or #TJCS_GRAY. + * + * @see TJPARAM_XDENSITY, TJPARAM_YDENSITY + */ + TJPARAM_DENSITYUNITS, + /** + * Memory limit for intermediate buffers + * + * **Value** + * - the maximum amount of memory (in megabytes) that will be allocated for + * intermediate buffers, which are used with progressive JPEG compression and + * decompression, Huffman table optimization, lossless JPEG compression, and + * lossless transformation *[default: `0` (no limit)]* + */ + TJPARAM_MAXMEMORY, + /** + * Image size limit [decompression, lossless transformation, packed-pixel + * image loading] + * + * Setting this parameter causes the decompression, transform, and image + * loading functions to return an error if the number of pixels in the source + * image exceeds the specified limit. This allows security-critical + * applications to guard against excessive memory consumption. + * + * **Value** + * - maximum number of pixels that the decompression, transform, and image + * loading functions will process *[default: `0` (no limit)]* + */ + TJPARAM_MAXPIXELS, + /** + * Marker copying behavior [decompression, lossless transformation, + * packed-pixel image I/O] + * + * **Value [lossless transformation]** + * - `0` Do not copy any extra markers (including comments, JFIF thumbnails, + * Exif data, and ICC profile data) from the source image to the destination + * image. + * - `1` Do not copy any extra markers, except comment (COM) markers, from + * the source image to the destination image. + * - `2` *[default]* Copy all extra markers from the source image to the + * destination image. + * - `3` Copy all extra markers, except ICC profile data (APP2 markers), from + * the source image to the destination image. + * - `4` Do not copy any extra markers, except ICC profile data (APP2 + * markers), from the source image to the destination image. + * + * #TJXOPT_COPYNONE overrides this parameter for a particular transform. + * This parameter overrides any ICC profile that was previously associated + * with the TurboJPEG instance using #tj3SetICCProfile(), #tj3LoadImage8(), + * #tj3LoadImage12(), or #tj3LoadImage16(). + * + * If this parameter is set to `2` or `4`: + * - When decompressing, #tj3DecompressHeader() extracts the ICC profile from + * a JPEG image. #tj3GetICCProfile() can then be used to retrieve the + * profile. + * - When loading a PNG image using a TurboJPEG compression instance, + * #tj3LoadImage8(), #tj3LoadImage12(), and #tj3LoadImage16() extract the + * ICC profile from the PNG image and associate the profile with the + * TurboJPEG instance. #tj3GetICCProfile() can then be used to retrieve + * the profile. + * - When saving a PNG image using a TurboJPEG decompression instance, + * #tj3SaveImage8(), #tj3SaveImage12(), and #tj3SaveImage16() transfer the + * ICC profile that was previously extracted from a JPEG image to the PNG + * image. + */ + TJPARAM_SAVEMARKERS +}; + + +/** + * The number of error codes + */ +#define TJ_NUMERR 2 + +/** + * Error codes + */ +enum TJERR { + /** + * The error was non-fatal and recoverable, but the destination image may + * still be corrupt. + */ + TJERR_WARNING, + /** + * The error was fatal and non-recoverable. + */ + TJERR_FATAL +}; + + +/** + * The number of transform operations + */ +#define TJ_NUMXOP 8 + +/** + * Transform operations for #tj3Transform() + */ +enum TJXOP { + /** + * Do not transform the position of the image pixels. + */ + TJXOP_NONE, + /** + * Flip (mirror) image horizontally. This transform is imperfect if there + * are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_HFLIP, + /** + * Flip (mirror) image vertically. This transform is imperfect if there are + * any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_VFLIP, + /** + * Transpose image (flip/mirror along upper left to lower right axis.) This + * transform is always perfect. + */ + TJXOP_TRANSPOSE, + /** + * Transverse transpose image (flip/mirror along upper right to lower left + * axis.) This transform is imperfect if there are any partial iMCUs in the + * image (see #TJXOPT_PERFECT.) + */ + TJXOP_TRANSVERSE, + /** + * Rotate image clockwise by 90 degrees. This transform is imperfect if + * there are any partial iMCUs on the bottom edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT90, + /** + * Rotate image 180 degrees. This transform is imperfect if there are any + * partial iMCUs in the image (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT180, + /** + * Rotate image counter-clockwise by 90 degrees. This transform is imperfect + * if there are any partial iMCUs on the right edge (see #TJXOPT_PERFECT.) + */ + TJXOP_ROT270 +}; + + +/** + * This option causes #tj3Transform() to return an error if the transform is + * not perfect. Lossless transforms operate on iMCUs, the size of which + * depends on the level of chrominance subsampling used (see #tjMCUWidth and + * #tjMCUHeight.) If the image's width or height is not evenly divisible by + * the iMCU size, then there will be partial iMCUs on the right and/or bottom + * edges. It is not possible to move these partial iMCUs to the top or left of + * the image, so any transform that would require that is "imperfect." If this + * option is not specified, then any partial iMCUs that cannot be transformed + * will be left in place, which will create odd-looking strips on the right or + * bottom edge of the image. + */ +#define TJXOPT_PERFECT (1 << 0) +/** + * Discard any partial iMCUs that cannot be transformed. + */ +#define TJXOPT_TRIM (1 << 1) +/** + * Enable lossless cropping. See #tj3Transform() for more information. + */ +#define TJXOPT_CROP (1 << 2) +/** + * Discard the color data in the source image, and generate a grayscale + * destination image. + */ +#define TJXOPT_GRAY (1 << 3) +/** + * Do not generate a destination image. (This can be used in conjunction with + * a custom filter to capture the transformed DCT coefficients without + * transcoding them.) + */ +#define TJXOPT_NOOUTPUT (1 << 4) +/** + * Generate a progressive destination image instead of a single-scan + * destination image. Progressive JPEG images generally have better + * compression ratios than single-scan JPEG images (much better if the image + * has large areas of solid color), but progressive JPEG decompression is + * considerably slower than single-scan JPEG decompression. Can be combined + * with #TJXOPT_ARITHMETIC. Implies #TJXOPT_OPTIMIZE unless #TJXOPT_ARITHMETIC + * is also specified. + */ +#define TJXOPT_PROGRESSIVE (1 << 5) +/** + * Do not copy any extra markers (including Exif and ICC profile data) from the + * source image to the destination image. + */ +#define TJXOPT_COPYNONE (1 << 6) +/** + * Enable arithmetic entropy coding in the destination image. Arithmetic + * entropy coding generally improves compression relative to Huffman entropy + * coding (the default), but it reduces decompression performance considerably. + * Can be combined with #TJXOPT_PROGRESSIVE. + */ +#define TJXOPT_ARITHMETIC (1 << 7) +/** + * Enable Huffman table optimization for the destination image. Huffman table + * optimization improves compression slightly (generally 5% or less.) + */ +#define TJXOPT_OPTIMIZE (1 << 8) + + +/** + * Scaling factor + */ +typedef struct { + /** + * Numerator + */ + int num; + /** + * Denominator + */ + int denom; +} tjscalingfactor; + +/** + * Cropping region + */ +typedef struct { + /** + * The left boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU width (see #tjMCUWidth) of the + * destination image. For decompression, this must be evenly divisible by + * the scaled iMCU width of the source image. + */ + int x; + /** + * The upper boundary of the cropping region. For lossless transformation, + * this must be evenly divisible by the iMCU height (see #tjMCUHeight) of the + * destination image. + */ + int y; + /** + * The width of the cropping region. Setting this to 0 is the equivalent of + * setting it to the width of the source JPEG image - x. + */ + int w; + /** + * The height of the cropping region. Setting this to 0 is the equivalent of + * setting it to the height of the source JPEG image - y. + */ + int h; +} tjregion; + +/** + * A #tjregion structure that specifies no cropping + */ +static const tjregion TJUNCROPPED = { 0, 0, 0, 0 }; + +/** + * Lossless transform + */ +typedef struct tjtransform { + /** + * Cropping region + */ + tjregion r; + /** + * One of the @ref TJXOP "transform operations" + */ + int op; + /** + * The bitwise OR of one of more of the @ref TJXOPT_ARITHMETIC + * "transform options" + */ + int options; + /** + * Arbitrary data that can be accessed within the body of the callback + * function + */ + void *data; + /** + * A callback function that can be used to modify the DCT coefficients after + * they are losslessly transformed but before they are transcoded to a new + * JPEG image. This allows for custom filters or other transformations to be + * applied in the frequency domain. + * + * @param coeffs pointer to an array of transformed DCT coefficients. (NOTE: + * This pointer is not guaranteed to be valid once the callback returns, so + * applications wishing to hand off the DCT coefficients to another function + * or library should make a copy of them within the body of the callback.) + * + * @param arrayRegion #tjregion structure containing the width and height of + * the array pointed to by `coeffs` as well as its offset relative to the + * component plane. TurboJPEG implementations may choose to split each + * component plane into multiple DCT coefficient arrays and call the callback + * function once for each array. + * + * @param planeRegion #tjregion structure containing the width and height of + * the component plane to which `coeffs` belongs + * + * @param componentID ID number of the component plane to which `coeffs` + * belongs. (Y, Cb, and Cr have, respectively, ID's of 0, 1, and 2 in + * typical JPEG images.) + * + * @param transformID ID number of the transformed image to which `coeffs` + * belongs. This is the same as the index of the transform in the + * `transforms` array that was passed to #tj3Transform(). + * + * @param transform a pointer to a #tjtransform structure that specifies the + * parameters and/or cropping region for this transform + * + * @return 0 if the callback was successful, or -1 if an error occurred. + */ + int (*customFilter) (short *coeffs, tjregion arrayRegion, + tjregion planeRegion, int componentID, int transformID, + struct tjtransform *transform); +} tjtransform; + +/** + * TurboJPEG instance handle + */ +typedef void *tjhandle; + + +/** + * Compute the scaled value of `dimension` using the given scaling factor. + * This macro performs the integer equivalent of `ceil(dimension * + * scalingFactor)`. + */ +#define TJSCALED(dimension, scalingFactor) \ + (((dimension) * scalingFactor.num + scalingFactor.denom - 1) / \ + scalingFactor.denom) + +/** + * A #tjscalingfactor structure that specifies a scaling factor of 1/1 (no + * scaling) + */ +static const tjscalingfactor TJUNSCALED = { 1, 1 }; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Create a new TurboJPEG instance. + * + * @param initType one of the @ref TJINIT "initialization options" + * + * @return a handle to the newly-created instance, or NULL if an error occurred + * (see #tj3GetErrorStr().) + */ +#ifdef __DOXYGEN__ +DLLEXPORT tjhandle tj3Init(int initType); +#else +#define tj3Init(initType) tj3InitVersion(initType, TURBOJPEG_VERSION_NUMBER) +#endif + +DLLEXPORT tjhandle tj3InitVersion(int initType, int apiVersion); + + +/** + * Destroy a TurboJPEG instance. + * + * @param handle handle to a TurboJPEG instance. If the handle is NULL, then + * this function has no effect. + */ +DLLEXPORT void tj3Destroy(tjhandle handle); + + +/** + * Returns a descriptive error message explaining why the last command failed. + * + * @param handle handle to a TurboJPEG instance, or NULL if the error was + * generated by a global function (but note that retrieving the error message + * for a global function is thread-safe only on platforms that support + * thread-local storage.) + * + * @return a descriptive error message explaining why the last command failed. + */ +DLLEXPORT char *tj3GetErrorStr(tjhandle handle); + + +/** + * Returns a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + * + * @param handle handle to a TurboJPEG instance + * + * @return a code indicating the severity of the last error. See + * @ref TJERR "Error codes". + */ +DLLEXPORT int tj3GetErrorCode(tjhandle handle); + + +/** + * Set the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @param value value of the parameter (refer to @ref TJPARAM + * "parameter documentation") + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3Set(tjhandle handle, int param, int value); + + +/** + * Get the value of a parameter. + * + * @param handle handle to a TurboJPEG instance + * + * @param param one of the @ref TJPARAM "parameters" + * + * @return the value of the specified parameter, or -1 if the value is unknown. + */ +DLLEXPORT int tj3Get(tjhandle handle, int param); + + +/** + * Allocate a byte buffer for use with TurboJPEG. You should always use this + * function to allocate the JPEG destination buffer(s) for the compression and + * transform functions unless you are disabling automatic buffer (re)allocation + * (by setting #TJPARAM_NOREALLOC.) + * + * @param bytes the number of bytes to allocate + * + * @return a pointer to a newly-allocated buffer with the specified number of + * bytes. + * + * @see tj3Free() + */ +DLLEXPORT void *tj3Alloc(size_t bytes); + + +/** + * Free a byte buffer previously allocated by TurboJPEG. You should always use + * this function to free JPEG destination buffer(s) that were automatically + * (re)allocated by the compression and transform functions or that were + * manually allocated using #tj3Alloc(). + * + * @param buffer address of the buffer to free. If the address is NULL, then + * this function has no effect. + * + * @see tj3Alloc() + */ +DLLEXPORT void tj3Free(void *buffer); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image with + * the given parameters. The number of bytes returned by this function is + * larger than the size of the uncompressed source image. The reason for this + * is that the JPEG format uses 16-bit coefficients, so it is possible for a + * very high-quality source image with very high-frequency content to expand + * rather than compress when converted to the JPEG format. Such images + * represent very rare corner cases, but since there is no way to predict the + * size of a JPEG image prior to compression, the corner cases have to be + * handled. + * + * @param width width (in pixels) of the image + * + * @param height height (in pixels) of the image + * + * @param jpegSubsamp the level of chrominance subsampling to be used when + * generating the JPEG image (see @ref TJSAMP + * "Chrominance subsampling options".) #TJSAMP_UNKNOWN is treated like + * #TJSAMP_444, since a buffer large enough to hold a JPEG image with no + * subsampling should also be large enough to hold a JPEG image with an + * arbitrary level of subsampling. Note that lossless JPEG images always + * use #TJSAMP_444. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * image, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3JPEGBufSize(int width, int height, int jpegSubsamp); + + +/** + * The size of the buffer (in bytes) required to hold a unified planar YUV + * image with the given parameters. + * + * @param width width (in pixels) of the image + * + * @param align row alignment (in bytes) of the image (must be a power of 2.) + * Setting this parameter to n specifies that each row in each plane of the + * image will be padded to the nearest multiple of n bytes (1 = unpadded.) + * + * @param height height (in pixels) of the image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the image, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVBufSize(int width, int align, int height, int subsamp); + + +/** + * The size of the buffer (in bytes) required to hold a YUV image plane with + * the given parameters. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image. NOTE: This is the width of + * the whole image, not the plane width. + * + * @param stride bytes per row in the image plane. Setting this to 0 is the + * equivalent of setting it to the plane width. + * + * @param height height (in pixels) of the YUV image. NOTE: This is the height + * of the whole image, not the plane height. + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the size of the buffer (in bytes) required to hold the YUV image + * plane, or 0 if the arguments are out of bounds. + */ +DLLEXPORT size_t tj3YUVPlaneSize(int componentID, int width, int stride, + int height, int subsamp); + + +/** + * The plane width of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane width. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param width width (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane width of a YUV image plane with the given parameters, or 0 + * if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneWidth(int componentID, int width, int subsamp); + + +/** + * The plane height of a YUV image plane with the given parameters. Refer to + * @ref YUVnotes "YUV Image Format Notes" for a description of plane height. + * + * @param componentID ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr) + * + * @param height height (in pixels) of the YUV image + * + * @param subsamp level of chrominance subsampling in the image (see + * @ref TJSAMP "Chrominance subsampling options".) + * + * @return the plane height of a YUV image plane with the given parameters, or + * 0 if the arguments are out of bounds. + */ +DLLEXPORT int tj3YUVPlaneHeight(int componentID, int height, int subsamp); + + +/** + * Embed an ICC (International Color Consortium) color management profile in + * JPEG images generated by subsequent compression and lossless transformation + * operations. + * + * @note Lossless transformation operations ignore this ICC profile unless + * #TJXOPT_COPYNONE is specified or #TJPARAM_SAVEMARKERS is set to something + * other than `2` or `4`. Otherwise the ICC profile in the source image takes + * precedence, even if the source image has no ICC profile. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param iccBuf pointer to a byte buffer containing an ICC profile. A copy is + * made of the ICC profile, so this buffer can be freed or reused as soon as + * this function returns. Setting this parameter to NULL or setting `iccSize` + * to 0 removes any ICC profile that was previously associated with the + * TurboJPEG instance. + * + * @param iccSize size of the ICC profile (in bytes.) Setting this parameter + * to 0 or setting `iccBuf` to NULL removes any ICC profile that was previously + * associated with the TurboJPEG instance. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetICCProfile(tjhandle handle, unsigned char *iccBuf, + size_t iccSize); + + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 2 to 8 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 9 to 12 bits of + * data precision per sample into a JPEG image with the same data precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress12(tjhandle handle, const short *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + +/** + * Compress a packed-pixel RGB, grayscale, or CMYK image with 13 to 16 bits of + * data precision per sample into a lossless JPEG image with the same data + * precision. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK source image to be compressed. This buffer should normally be + * `pitch * height` samples in size. However, you can also use this parameter + * to compress from a specific region of a larger buffer. The data precision + * of the source image (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param width width (in pixels) of the source image + * + * @param pitch samples per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to compress from a specific region of a larger buffer. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Compress16(tjhandle handle, const unsigned short *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Compress a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into + * an 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or + * @ref TJCS_GRAY "grayscale" JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if compressing a grayscale image) that contain a YUV + * source image to be compressed. These planes can be contiguous or + * non-contiguous in memory. The size of each plane should match the value + * returned by #tj3YUVPlaneSize() for the given image width, height, strides, + * and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer to + * @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to create a JPEG image from a subregion of a larger + * planar YUV image. + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + int width, const int *strides, + int height, unsigned char **jpegBuf, + size_t *jpegSize); + + +/** + * Compress an 8-bit-per-sample unified planar YUV image into an + * 8-bit-per-sample lossy @ref TJCS_YCbCr "YCbCr" or @ref TJCS_GRAY "grayscale" + * JPEG image. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be compressed. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param width width (in pixels) of the source image. If the width is not an + * even multiple of the iMCU width (see #tjMCUWidth), then an intermediate + * buffer copy will be performed. + * + * @param align row alignment (in bytes) of the source image (must be a power + * of 2.) Setting this parameter to n indicates that each row in each plane of + * the source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param height height (in pixels) of the source image. If the height is not + * an even multiple of the iMCU height (see #tjMCUHeight), then an intermediate + * buffer copy will be performed. + * + * @param jpegBuf address of a pointer to a byte buffer that will receive the + * JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to + * accommodate the size of the JPEG image. Thus, you can choose to: + * -# pre-allocate the JPEG buffer with an arbitrary size using #tj3Alloc() and + * let TurboJPEG grow the buffer as needed, + * -# set `*jpegBuf` to NULL to tell TurboJPEG to allocate the buffer for you, + * or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3JPEGBufSize() and adding the return value to the size of the ICC profile + * (if any) that was previously associated with the TurboJPEG instance (see + * #tj3SetICCProfile() and #tj3GetICCProfile().) This should ensure that the + * buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC guarantees + * that it won't be.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `*jpegBuf` + * upon return from this function, as it may have changed. + * + * @param jpegSize pointer to a size_t variable that holds the size of the JPEG + * buffer. If `*jpegBuf` points to a pre-allocated buffer, then `*jpegSize` + * should be set to the size of the buffer. Otherwise, `*jpegSize` is + * ignored. If `*jpegBuf` points to a JPEG buffer that is being reused from a + * previous call to one of the JPEG compression functions, then `*jpegSize` is + * also ignored. Upon return, `*jpegSize` will contain the size of the JPEG + * image (in bytes.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3CompressFromYUV8(tjhandle handle, + const unsigned char *srcBuf, int width, + int align, int height, + unsigned char **jpegBuf, size_t *jpegSize); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * color conversion and downsampling (which are accelerated in the + * libjpeg-turbo implementation) but does not execute any of the other steps in + * the JPEG compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if generating a grayscale image) that will receive the + * encoded image. These planes can be contiguous or non-contiguous in memory. + * Use #tj3YUVPlaneSize() to determine the appropriate size for each plane + * based on the image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the plane width (see @ref YUVnotes + * "YUV Image Format Notes".) If `strides` is NULL, then the strides for all + * planes will be set to their respective plane widths. You can adjust the + * strides in order to add an arbitrary amount of row padding to each plane or + * to encode an RGB or grayscale image into a subregion of a larger planar YUV + * image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUVPlanes8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides); + + +/** + * Encode an 8-bit-per-sample packed-pixel RGB or grayscale image into an + * 8-bit-per-sample unified planar YUV image. This function performs color + * conversion and downsampling (which are accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * compression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * compression + * + * @param srcBuf pointer to a buffer containing a packed-pixel RGB or grayscale + * source image to be encoded. This buffer should normally be `pitch * height` + * bytes in size. However, you can also use this parameter to encode from a + * specific region of a larger buffer. + * + * @param width width (in pixels) of the source image + * + * @param pitch bytes per row in the source image. Normally this should be + * width * #tjPixelSize[pixelFormat], if the image is unpadded. + * (Setting this parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat].) However, you can also use this + * parameter to specify the row alignment/padding of the source image, to skip + * rows, or to encode from a specific region of a larger packed-pixel image. + * + * @param height height (in pixels) of the source image + * + * @param pixelFormat pixel format of the source image (see @ref TJPF + * "Pixel formats".) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * image. Use #tj3YUVBufSize() to determine the appropriate size for this + * buffer based on the image width, height, row alignment, and level of + * chrominance subsampling (see #TJPARAM_SUBSAMP.) The Y, U (Cb), and V (Cr) + * image planes will be stored sequentially in the buffer. (Refer to + * @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3EncodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align); + + +/** + * Retrieve information about a JPEG image without decompressing it, or prime + * the decompressor with quantization and Huffman tables. If a JPEG image is + * passed to this function, then the @ref TJPARAM "parameters" that describe + * the JPEG image will be set when the function returns. If a JPEG image is + * passed to this function and #TJPARAM_SAVEMARKERS is set to `2` or `4`, then + * the ICC profile (if any) will be extracted from the JPEG image. + * (#tj3GetICCProfile() can then be used to retrieve the profile.) + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing a JPEG image or an + * "abbreviated table specification" (AKA "tables-only") datastream. Passing a + * tables-only datastream to this function primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. + * + * @param jpegSize size of the JPEG image or tables-only datastream (in bytes) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressHeader(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize); + + +/** + * Retrieve the ICC (International Color Consortium) color management profile + * (if any) that was previously extracted from a JPEG image or associated with + * a TurboJPEG compression instance. + * + * @note To extract the ICC profile from a JPEG image, call + * #tj3DecompressHeader() with #TJPARAM_SAVEMARKERS set to `2` or `4`. + * + * @note To associate an ICC profile with a TurboJPEG compression instance, + * call #tj3SetICCProfile() or use #tj3LoadImage8(), #tj3LoadImage12(), or + * #tj3LoadImage16() to load a PNG image with #TJPARAM_SAVEMARKERS set to `2` + * or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param iccBuf address of a pointer to a byte buffer. Upon return: + * - If `iccBuf` is not NULL and there is an ICC profile to retrieve, then + * `*iccBuf` will point to a byte buffer containing the ICC profile. This + * buffer should be freed using #tj3Free(). + * - If `iccBuf` is not NULL and there is no ICC profile to retrieve, then + * `*iccBuf` will be NULL. + * - If `iccBuf` is NULL, then only the ICC profile size will be retrieved, and + * the ICC profile can be retrieved later. + * + * @param iccSize address of a size_t variable. Upon return, the variable will + * contain the ICC profile size (or 0 if there is no ICC profile to retrieve.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3GetICCProfile(tjhandle handle, unsigned char **iccBuf, + size_t *iccSize); + + +/** + * Returns a list of fractional scaling factors that the JPEG decompressor + * supports. + * + * @param numScalingFactors pointer to an integer variable that will receive + * the number of elements in the list + * + * @return a pointer to a list of fractional scaling factors, or NULL if an + * error is encountered (see #tj3GetErrorStr().) + */ +DLLEXPORT tjscalingfactor *tj3GetScalingFactors(int *numScalingFactors); + + +/** + * Set the scaling factor for subsequent lossy decompression operations. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param scalingFactor #tjscalingfactor structure that specifies a fractional + * scaling factor that the decompressor supports (see #tj3GetScalingFactors()), + * or #TJUNSCALED for no scaling. Decompression scaling is a function + * of the IDCT algorithm, so scaling factors are generally limited to multiples + * of 1/8. If the entire JPEG image will be decompressed, then the width and + * height of the scaled destination image can be determined by calling + * #TJSCALED() with the JPEG width and height (see #TJPARAM_JPEGWIDTH and + * #TJPARAM_JPEGHEIGHT) and the specified scaling factor. When decompressing + * into a planar YUV image, an intermediate buffer copy will be performed if + * the width or height of the scaled destination image is not an even multiple + * of the iMCU size (see #tjMCUWidth and #tjMCUHeight.) Note that + * decompression scaling is not available (and the specified scaling factor is + * ignored) when decompressing lossless JPEG images (see #TJPARAM_LOSSLESS), + * since the IDCT algorithm is not used with those images. Note also that + * #TJPARAM_FASTDCT is ignored when decompression scaling is enabled. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetScalingFactor(tjhandle handle, + tjscalingfactor scalingFactor); + + +/** + * Set the cropping region for partially decompressing a lossy JPEG image into + * a packed-pixel image + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param croppingRegion #tjregion structure that specifies a subregion of the + * JPEG image to decompress, or #TJUNCROPPED for no cropping. The + * left boundary of the cropping region must be evenly divisible by the scaled + * iMCU width-- #TJSCALED(#tjMCUWidth[subsamp], scalingFactor), where + * `subsamp` is the level of chrominance subsampling in the JPEG image (see + * #TJPARAM_SUBSAMP) and `scalingFactor` is the decompression scaling factor + * (see #tj3SetScalingFactor().) The cropping region should be specified + * relative to the scaled image dimensions. Unless `croppingRegion` is + * #TJUNCROPPED, the JPEG header must be read (see + * #tj3DecompressHeader()) prior to calling this function. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SetCroppingRegion(tjhandle handle, tjregion croppingRegion); + + +/** + * Decompress a JPEG image with 2 to 8 bits of data precision per sample into a + * packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * The @ref TJPARAM "parameters" that describe the JPEG image will be set when + * this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel + * decompressed image. This buffer should normally be + * `pitch * destinationHeight` samples in size. However, you can also use this + * parameter to decompress into a specific region of a larger buffer. NOTE: + * If the JPEG image is lossy, then `destinationHeight` is either the scaled + * JPEG height (see #TJSCALED(), #TJPARAM_JPEGHEIGHT, and + * #tj3SetScalingFactor()) or the height of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationHeight` is the JPEG height. + * + * @param pitch samples per row in the destination image. Normally this should + * be set to destinationWidth * #tjPixelSize[pixelFormat], if the + * destination image should be unpadded. (Setting this parameter to 0 is the + * equivalent of setting it to + * destinationWidth * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decompress into a specific region of + * a larger buffer. NOTE: If the JPEG image is lossy, then `destinationWidth` + * is either the scaled JPEG width (see #TJSCALED(), #TJPARAM_JPEGWIDTH, and + * #tj3SetScalingFactor()) or the width of the cropping region (see + * #tj3SetCroppingRegion().) If the JPEG image is lossless, then + * `destinationWidth` is the JPEG width. + * + * @param pixelFormat pixel format of the destination image (see @ref + * TJPF "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Decompress8(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned char *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a JPEG image with 9 to 12 bits of data precision per sample into + * a packed-pixel RGB, grayscale, or CMYK image with the same data precision. + * + * @note This function can also be used to decompress an 8-bit-per-sample lossy + * JPEG image into a 12-bit-per-sample packed-pixel image. + * + * @note The JPEG format uses 16-bit DCT coefficients and computes those + * coefficients relative to an 8x8 DCT block. Thus, an 8-bit-per-sample JPEG + * image can preserve most of the signal from an underexposed + * higher-data-precision source image, provided that the data precision of the + * source image is retained in the compressor until the forward DCT stage. + * (Modern digital cameras typically do that, but note that libjpeg-turbo does + * not. Our solution for retaining higher data precision in the compressor is + * simply to generate a 12-bit-per-sample JPEG image.) + * + * @note It may be desirable to preserve as much of that signal as possible in + * the decompressor, to facilitate shadow recovery in the decompressed image. + * Thus, calling this function forces the decompressor to use the + * 12-bit-per-sample decompression pipeline even if the JPEG image has 8 bits + * of data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress12(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, short *dstBuf, int pitch, + int pixelFormat); + +/** + * Decompress a lossless JPEG image with 13 to 16 bits of data precision per + * sample into a packed-pixel RGB, grayscale, or CMYK image with the same + * data precision. + * + * \details \copydetails tj3Decompress8() + */ +DLLEXPORT int tj3Decompress16(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, unsigned short *dstBuf, + int pitch, int pixelFormat); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into separate + * 8-bit-per-sample Y, U (Cb), and V (Cr) image planes. This function performs + * JPEG decompression but leaves out the color conversion step, so a planar YUV + * image is generated instead of a packed-pixel image. The + * @ref TJPARAM "parameters" that describe the JPEG image will be set when this + * function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decompressing a grayscale image) that will receive + * the decompressed image. These planes can be contiguous or non-contiguous in + * memory. Use #tj3YUVPlaneSize() to determine the appropriate size for each + * plane based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), + * strides, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) Refer + * to @ref YUVnotes "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV image. Setting the stride for any + * plane to 0 is the same as setting it to the scaled plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective scaled plane widths. + * You can adjust the strides in order to add an arbitrary amount of row + * padding to each plane or to decompress the JPEG image into a subregion of a + * larger planar YUV image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char **dstPlanes, + int *strides); + + +/** + * Decompress an 8-bit-per-sample lossy JPEG image into an 8-bit-per-sample + * unified planar YUV image. This function performs JPEG decompression but + * leaves out the color conversion step, so a planar YUV image is generated + * instead of a packed-pixel image. The @ref TJPARAM "parameters" that + * describe the JPEG image will be set when this function returns. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param jpegBuf pointer to a byte buffer containing the JPEG image to + * decompress + * + * @param jpegSize size of the JPEG image (in bytes) + * + * @param dstBuf pointer to a buffer that will receive the unified planar YUV + * decompressed image. Use #tj3YUVBufSize() to determine the appropriate size + * for this buffer based on the scaled JPEG width and height (see #TJSCALED(), + * #TJPARAM_JPEGWIDTH, #TJPARAM_JPEGHEIGHT, and #tj3SetScalingFactor()), row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes will be stored sequentially in the + * buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV image (must be a power of + * 2.) Setting this parameter to n will cause each row in each plane of the + * YUV image to be padded to the nearest multiple of n bytes (1 = unpadded.) + * To generate images suitable for X Video, `align` should be set to 4. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecompressToYUV8(tjhandle handle, + const unsigned char *jpegBuf, + size_t jpegSize, + unsigned char *dstBuf, int align); + + +/** + * Decode a set of 8-bit-per-sample Y, U (Cb), and V (Cr) image planes into an + * 8-bit-per-sample packed-pixel RGB or grayscale image. This function + * performs color conversion (which is accelerated in the libjpeg-turbo + * implementation) but does not execute any of the other steps in the JPEG + * decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcPlanes an array of pointers to Y, U (Cb), and V (Cr) image planes + * (or just a Y plane, if decoding a grayscale image) that contain a YUV image + * to be decoded. These planes can be contiguous or non-contiguous in memory. + * The size of each plane should match the value returned by #tj3YUVPlaneSize() + * for the given image width, height, strides, and level of chrominance + * subsampling (see #TJPARAM_SUBSAMP.) Refer to @ref YUVnotes + * "YUV Image Format Notes" for more details. + * + * @param strides an array of integers, each specifying the number of bytes per + * row in the corresponding plane of the YUV source image. Setting the stride + * for any plane to 0 is the same as setting it to the plane width (see + * @ref YUVnotes "YUV Image Format Notes".) If `strides` is NULL, then the + * strides for all planes will be set to their respective plane widths. You + * can adjust the strides in order to specify an arbitrary amount of row + * padding in each plane or to decode a subregion of a larger planar YUV image. + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUVPlanes8(tjhandle handle, + const unsigned char * const *srcPlanes, + const int *strides, unsigned char *dstBuf, + int width, int pitch, int height, + int pixelFormat); + + +/** + * Decode an 8-bit-per-sample unified planar YUV image into an 8-bit-per-sample + * packed-pixel RGB or grayscale image. This function performs color + * conversion (which is accelerated in the libjpeg-turbo implementation) but + * does not execute any of the other steps in the JPEG decompression process. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * decompression + * + * @param srcBuf pointer to a buffer containing a unified planar YUV source + * image to be decoded. The size of this buffer should match the value + * returned by #tj3YUVBufSize() for the given image width, height, row + * alignment, and level of chrominance subsampling (see #TJPARAM_SUBSAMP.) The + * Y, U (Cb), and V (Cr) image planes should be stored sequentially in the + * source buffer. (Refer to @ref YUVnotes "YUV Image Format Notes".) + * + * @param align row alignment (in bytes) of the YUV source image (must be a + * power of 2.) Setting this parameter to n indicates that each row in each + * plane of the YUV source image is padded to the nearest multiple of n bytes + * (1 = unpadded.) + * + * @param dstBuf pointer to a buffer that will receive the packed-pixel decoded + * image. This buffer should normally be `pitch * height` bytes in size. + * However, you can also use this parameter to decode into a specific region of + * a larger buffer. + * + * @param width width (in pixels) of the source and destination images + * + * @param pitch bytes per row in the destination image. Normally this should + * be set to width * #tjPixelSize[pixelFormat], if the destination + * image should be unpadded. (Setting this parameter to 0 is the equivalent of + * setting it to width * #tjPixelSize[pixelFormat].) However, you can + * also use this parameter to specify the row alignment/padding of the + * destination image, to skip rows, or to decode into a specific region of a + * larger buffer. + * + * @param height height (in pixels) of the source and destination images + * + * @param pixelFormat pixel format of the destination image (see @ref TJPF + * "Pixel formats".) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3DecodeYUV8(tjhandle handle, const unsigned char *srcBuf, + int align, unsigned char *dstBuf, int width, + int pitch, int height, int pixelFormat); + + +/** + * The maximum size of the buffer (in bytes) required to hold a JPEG image + * transformed with the given transform parameters and/or cropping region. + * This function is a wrapper for #tj3JPEGBufSize() that takes into account + * cropping, transposition of the width and height (which affects the + * destination image dimensions and level of chrominance subsampling), + * grayscale conversion, and the ICC profile (if any) that was previously + * associated with the TurboJPEG instance or extracted from the source image + * (see #tj3SetICCProfile(), #tj3GetICCProfile(), and #TJPARAM_SAVEMARKERS.) + * The JPEG header must be read (see #tj3DecompressHeader()) prior to calling + * this function. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param transform pointer to a #tjtransform structure that specifies the + * transform parameters and/or cropping region for the JPEG image. + * + * @return the maximum size of the buffer (in bytes) required to hold the + * transformed image, or 0 if an error occurred (see #tj3GetErrorStr() and + * #tj3GetErrorCode().) + */ +DLLEXPORT size_t tj3TransformBufSize(tjhandle handle, + const tjtransform *transform); + + +/** + * Losslessly transform a JPEG image into another JPEG image. Lossless + * transforms work by moving the raw DCT coefficients from one JPEG image + * structure to another without altering the values of the coefficients. While + * this is typically faster than decompressing the image, transforming it, and + * re-compressing it, lossless transforms are not free. Each lossless + * transform requires reading and performing entropy decoding on all of the + * coefficients in the source image, regardless of the size of the destination + * image. Thus, this function provides a means of generating multiple + * transformed images from the same source or applying multiple transformations + * simultaneously, in order to eliminate the need to read the source + * coefficients multiple times. + * + * @param handle handle to a TurboJPEG instance that has been initialized for + * lossless transformation + * + * @param jpegBuf pointer to a byte buffer containing the JPEG source image to + * transform + * + * @param jpegSize size of the JPEG source image (in bytes) + * + * @param n the number of transformed JPEG images to generate + * + * @param dstBufs pointer to an array of n byte buffers. `dstBufs[i]` will + * receive a JPEG image that has been transformed using the parameters in + * `transforms[i]`. TurboJPEG has the ability to reallocate the JPEG + * destination buffer to accommodate the size of the transformed JPEG image. + * Thus, you can choose to: + * -# pre-allocate the JPEG destination buffer with an arbitrary size using + * #tj3Alloc() and let TurboJPEG grow the buffer as needed, + * -# set `dstBufs[i]` to NULL to tell TurboJPEG to allocate the buffer for + * you, or + * -# pre-allocate the buffer to a "worst case" size determined by calling + * #tj3TransformBufSize(). Under normal circumstances, this should ensure that + * the buffer never has to be re-allocated. (Setting #TJPARAM_NOREALLOC + * guarantees that it won't be. However, if the source image has a large + * amount of embedded Exif data, then the transformed JPEG image may be larger + * than the worst-case size. #TJPARAM_NOREALLOC cannot be used in that case + * unless the embedded data is discarded using #TJXOPT_COPYNONE or + * #TJPARAM_SAVEMARKERS.) + * . + * Unless you have set #TJPARAM_NOREALLOC, you should always check `dstBufs[i]` + * upon return from this function, as it may have changed. + * + * @param dstSizes pointer to an array of n size_t variables that will receive + * the actual sizes (in bytes) of each transformed JPEG image. If `dstBufs[i]` + * points to a pre-allocated buffer, then `dstSizes[i]` should be set to the + * size of the buffer. Otherwise, `dstSizes[i]` is ignored. Upon return, + * `dstSizes[i]` will contain the size of the transformed JPEG image (in + * bytes.) + * + * @param transforms pointer to an array of n #tjtransform structures, each of + * which specifies the transform parameters and/or cropping region for the + * corresponding transformed JPEG image. + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr() + * and #tj3GetErrorCode().) + */ +DLLEXPORT int tj3Transform(tjhandle handle, const unsigned char *jpegBuf, + size_t jpegSize, int n, unsigned char **dstBufs, + size_t *dstSizes, const tjtransform *transforms); + + +/** + * Load a packed-pixel image with 2 to 8 bits of data precision per sample from + * disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG, + * PBMPLUS (PPM/PGM), or Windows BMP format. Windows BMP files require + * 8-bit-per-sample data precision. When loading a PNG or PBMPLUS file, the + * target data precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. If the data precision of the PNG or PBMPLUS file does not match + * the target data precision, then upconverting or downconverting will be + * performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function varies depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files and 8-bit-per-pixel BMP files with a + * grayscale colormap can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned char *tj3LoadImage8(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 9 to 12 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 9 to 12 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 12 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT short *tj3LoadImage12(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + +/** + * Load a packed-pixel image with 13 to 16 bits of data precision per sample + * from disk into memory. + * + * @note If loading a PNG image using a TurboJPEG compression instance, the + * ICC profile (if any) embedded in the PNG image is extracted and associated + * with the TurboJPEG instance if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file containing a packed-pixel image in PNG or + * PBMPLUS (PPM/PGM) format. The target data precision (from 13 to 16 bits per + * sample) can be specified using #TJPARAM_PRECISION and defaults to 16 if + * #TJPARAM_PRECISION is unset or out of range. If the data precision of the + * PNG or PBMPLUS file does not match the target data precision, then + * upconverting or downconverting will be performed. + * + * @param width pointer to an integer variable that will receive the width (in + * pixels) of the packed-pixel image + * + * @param align row alignment (in samples) of the packed-pixel buffer to be + * returned (must be a power of 2.) Setting this parameter to n will cause all + * rows in the buffer to be padded to the nearest multiple of n samples + * (1 = unpadded.) + * + * @param height pointer to an integer variable that will receive the height + * (in pixels) of the packed-pixel image + * + * @param pixelFormat pointer to an integer variable that specifies or will + * receive the pixel format of the packed-pixel buffer. The behavior of this + * function will vary depending on the value of `*pixelFormat` passed to the + * function: + * - @ref TJPF_UNKNOWN : The packed-pixel buffer returned by this function will + * use the most optimal pixel format for the file type, and `*pixelFormat` will + * contain the ID of that pixel format upon successful return from this + * function. + * - @ref TJPF_GRAY : Only PGM files can be loaded. + * - @ref TJPF_CMYK : The RGB or grayscale pixels stored in the file will be + * converted using a quick & dirty algorithm that is suitable only for testing + * purposes. (Proper conversion between CMYK and other formats requires a + * color management system.) + * - Other @ref TJPF "pixel formats" : The packed-pixel buffer will use the + * specified pixel format, and pixel format conversion will be performed if + * necessary. + * + * @return a pointer to a newly-allocated buffer containing the packed-pixel + * image, converted to the chosen pixel format and with the chosen row + * alignment, or NULL if an error occurred (see #tj3GetErrorStr().) This + * buffer should be freed using #tj3Free(). + */ +DLLEXPORT unsigned short *tj3LoadImage16(tjhandle handle, const char *filename, + int *width, int align, int *height, + int *pixelFormat); + + +/** + * Save a packed-pixel image with 2 to 8 bits of data precision per sample from + * memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image. The + * image will be stored in PNG, PBMPLUS (PPM/PGM), or Windows BMP format, + * depending on the file extension. Windows BMP files require 8-bit-per-sample + * data precision. When saving a PNG or PBMPLUS file, the source data + * precision (from 2 to 8 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 8 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in grayscale PNG, PGM, or 8-bit-per-pixel (indexed + * color) BMP format. Otherwise, the image will be stored in truecolor PNG, + * PPM, or 24-bit-per-pixel BMP format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage8(tjhandle handle, const char *filename, + const unsigned char *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 9 to 12 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 9 to 12 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 12 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage12(tjhandle handle, const char *filename, + const short *buffer, int width, int pitch, + int height, int pixelFormat); + +/** + * Save a packed-pixel image with 13 to 16 bits of data precision per sample + * from memory to disk. + * + * @note If saving a PNG image using a TurboJPEG decompression instance, the + * ICC profile (if any) that was previously extracted from a JPEG image is + * transferred to the PNG image if #TJPARAM_SAVEMARKERS is set to `2` or `4`. + * + * @param handle handle to a TurboJPEG instance + * + * @param filename name of a file to which to save the packed-pixel image, + * which will be stored in PNG or PBMPLUS (PPM/PGM) format. The source data + * precision (from 13 to 16 bits per sample) can be specified using + * #TJPARAM_PRECISION and defaults to 16 if #TJPARAM_PRECISION is unset or out + * of range. + * + * @param buffer pointer to a buffer containing a packed-pixel RGB, grayscale, + * or CMYK image to be saved + * + * @param width width (in pixels) of the packed-pixel image + * + * @param pitch samples per row in the packed-pixel image. Setting this + * parameter to 0 is the equivalent of setting it to + * width * #tjPixelSize[pixelFormat]. + * + * @param height height (in pixels) of the packed-pixel image + * + * @param pixelFormat pixel format of the packed-pixel image (see @ref TJPF + * "Pixel formats".) If this parameter is set to @ref TJPF_GRAY, then the + * image will be stored in PGM or grayscale PNG format. Otherwise, the image + * will be stored in PPM or truecolor PNG format. If this parameter is set to + * @ref TJPF_CMYK, then the CMYK pixels will be converted to RGB using a quick + * & dirty algorithm that is suitable only for testing purposes. (Proper + * conversion between CMYK and other formats requires a color management + * system.) + * + * @return 0 if successful, or -1 if an error occurred (see #tj3GetErrorStr().) + */ +DLLEXPORT int tj3SaveImage16(tjhandle handle, const char *filename, + const unsigned short *buffer, int width, + int pitch, int height, int pixelFormat); + + +/* Backward compatibility functions and macros (nothing to see here) */ + +/* TurboJPEG 1.0+ */ + +#define NUMSUBOPT TJ_NUMSAMP +#define TJ_444 TJSAMP_444 +#define TJ_422 TJSAMP_422 +#define TJ_420 TJSAMP_420 +#define TJ_411 TJSAMP_420 +#define TJ_GRAYSCALE TJSAMP_GRAY + +#define TJ_BGR 1 +#define TJ_BOTTOMUP TJFLAG_BOTTOMUP +#define TJ_FORCEMMX TJFLAG_FORCEMMX +#define TJ_FORCESSE TJFLAG_FORCESSE +#define TJ_FORCESSE2 TJFLAG_FORCESSE2 +#define TJ_ALPHAFIRST 64 +#define TJ_FORCESSE3 TJFLAG_FORCESSE3 +#define TJ_FASTUPSAMPLE TJFLAG_FASTUPSAMPLE + +#define TJPAD(width) (((width) + 3) & (~3)) + +DLLEXPORT unsigned long TJBUFSIZE(int width, int height); + +DLLEXPORT int tjCompress(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, unsigned long *compressedSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelSize, + int flags); + +DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height); + +DLLEXPORT int tjDestroy(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr(void); + +DLLEXPORT tjhandle tjInitCompress(void); + +DLLEXPORT tjhandle tjInitDecompress(void); + +/* TurboJPEG 1.1+ */ + +#define TJ_YUV 512 + +DLLEXPORT unsigned long TJBUFSIZEYUV(int width, int height, int jpegSubsamp); + +DLLEXPORT int tjDecompressHeader2(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp); + +DLLEXPORT int tjDecompressToYUV(tjhandle handle, unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int flags); + +DLLEXPORT int tjEncodeYUV(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelSize, + unsigned char *dstBuf, int subsamp, int flags); + +/* TurboJPEG 1.2+ */ + +#define TJFLAG_BOTTOMUP 2 +#define TJFLAG_FORCEMMX 8 +#define TJFLAG_FORCESSE 16 +#define TJFLAG_FORCESSE2 32 +#define TJFLAG_FORCESSE3 128 +#define TJFLAG_FASTUPSAMPLE 256 +#define TJFLAG_NOREALLOC 1024 + +DLLEXPORT unsigned char *tjAlloc(int bytes); + +DLLEXPORT unsigned long tjBufSize(int width, int height, int jpegSubsamp); + +DLLEXPORT unsigned long tjBufSizeYUV(int width, int height, int subsamp); + +DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char **jpegBuf, unsigned long *jpegSize, + int jpegSubsamp, int jpegQual, int flags); + +DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf, int width, + int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int subsamp, int flags); + +DLLEXPORT void tjFree(unsigned char *buffer); + +DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors); + +DLLEXPORT tjhandle tjInitTransform(void); + +DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, int n, + unsigned char **dstBufs, unsigned long *dstSizes, + tjtransform *transforms, int flags); + +/* TurboJPEG 1.2.1+ */ + +#define TJFLAG_FASTDCT 2048 +#define TJFLAG_ACCURATEDCT 4096 + +/* TurboJPEG 1.4+ */ + +DLLEXPORT unsigned long tjBufSizeYUV2(int width, int align, int height, + int subsamp); + +DLLEXPORT int tjCompressFromYUV(tjhandle handle, const unsigned char *srcBuf, + int width, int align, int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + int width, const int *strides, + int height, int subsamp, + unsigned char **jpegBuf, + unsigned long *jpegSize, int jpegQual, + int flags); + +DLLEXPORT int tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, + int align, int subsamp, unsigned char *dstBuf, + int width, int pitch, int height, int pixelFormat, + int flags); + +DLLEXPORT int tjDecodeYUVPlanes(tjhandle handle, + const unsigned char **srcPlanes, + const int *strides, int subsamp, + unsigned char *dstBuf, int width, int pitch, + int height, int pixelFormat, int flags); + +DLLEXPORT int tjDecompressHeader3(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, int *width, + int *height, int *jpegSubsamp, + int *jpegColorspace); + +DLLEXPORT int tjDecompressToYUV2(tjhandle handle, const unsigned char *jpegBuf, + unsigned long jpegSize, unsigned char *dstBuf, + int width, int align, int height, int flags); + +DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle, + const unsigned char *jpegBuf, + unsigned long jpegSize, + unsigned char **dstPlanes, int width, + int *strides, int height, int flags); + +DLLEXPORT int tjEncodeYUV3(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, int pixelFormat, + unsigned char *dstBuf, int align, int subsamp, + int flags); + +DLLEXPORT int tjEncodeYUVPlanes(tjhandle handle, const unsigned char *srcBuf, + int width, int pitch, int height, + int pixelFormat, unsigned char **dstPlanes, + int *strides, int subsamp, int flags); + +DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); + +DLLEXPORT unsigned long tjPlaneSizeYUV(int componentID, int width, int stride, + int height, int subsamp); + +DLLEXPORT int tjPlaneWidth(int componentID, int width, int subsamp); + +/* TurboJPEG 2.0+ */ + +#define TJFLAG_STOPONWARNING 8192 +#define TJFLAG_PROGRESSIVE 16384 + +DLLEXPORT int tjGetErrorCode(tjhandle handle); + +DLLEXPORT char *tjGetErrorStr2(tjhandle handle); + +DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width, + int align, int *height, int *pixelFormat, + int flags); + +DLLEXPORT int tjSaveImage(const char *filename, unsigned char *buffer, + int width, int pitch, int height, int pixelFormat, + int flags); + +/* TurboJPEG 2.1+ */ + +#define TJFLAG_LIMITSCANS 32768 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/zconf.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/zconf.h new file mode 100644 index 0000000..1ff5e8c --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/zconf.h @@ -0,0 +1,555 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* #undef Z_PREFIX */ +#define HAVE_STDARG_H 1 +#define HAVE_UNISTD_H 1 + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compress_z z_compress_z +# define compress2_z z_compress2_z +# define compressBound z_compressBound +# define compressBound_z z_compressBound_z +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateBound_z z_deflateBound_z +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflateUsed z_deflateUsed +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define inflate_fixed z_inflate_fixed +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# define uncompress_z z_uncompress_z +# define uncompress2_z z_uncompress2_z +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#ifndef z_const +# ifdef ZLIB_CONST +# define z_const const +# else +# define z_const +# endif +#endif + +#ifdef Z_SOLO +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if HAVE_UNISTD_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#if HAVE_STDARG_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# if defined(__WATCOMC__) || defined(__GO32__) || \ + (defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#elif defined(__MINGW32__) +# define z_off64_t long long +#elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +#elif defined(__GO32__) +# define z_off64_t offset_t +#else +# define z_off64_t z_off_t +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/zlib.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/zlib.h new file mode 100644 index 0000000..a57d336 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/zlib.h @@ -0,0 +1,2057 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.3.2, February 17th, 2026 + + Copyright (C) 1995-2026 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 at https://datatracker.ietf.org/doc/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#ifdef ZLIB_BUILD +# include +#else +# include "zconf.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.3.2" +#define ZLIB_VERNUM 0x1320 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 2 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion(void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the input taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_RLE to limit match distances to one (run-length + encoding), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string + matching). Filtered data consists mostly of small values with a somewhat + random distribution, as produced by the PNG filters. In this case, the + compression algorithm is tuned to compress them better. The effect of + Z_FILTERED is to force more Huffman coding and less string matching than the + default; it is intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. + Z_RLE is almost as fast as Z_HUFFMAN_ONLY, but should give better + compression for PNG image data than Huffman only. The degree of string + matching from most to none is: Z_DEFAULT_STRATEGY, Z_FILTERED, Z_RLE, then + Z_HUFFMAN_ONLY. The strategy parameter affects the compression ratio but + never the correctness of the compressed output, even if it is not set + optimally for the given data. Z_FIXED uses the default string matching, but + prevents the use of dynamic Huffman codes, allowing for a simpler decoder + for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); +ZEXTERN z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. + + delfateBound_z() is the same, but takes and returns a size_t length. Note + that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. If an int is 16 bits and memLevel is 9, then + it is possible for the number of pending bytes to not fit in an unsigned. In + that case Z_BUF_ERROR is returned and *pending is set to the maximum value + of an unsigned. + */ + +ZEXTERN int ZEXPORT deflateUsed(z_streamp strm, + int *bits); +/* + deflateUsed() returns in *bits the most recent number of deflate bits used + in the last byte when flushing to a byte boundary. The result is in 1..8, or + 0 if there has not yet been a flush. This helps determine the location of + the last bit of a deflate stream. + + deflateUsed returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); +/* + This function inserts bits in the inflate input stream. The intent is to + use inflatePrime() to start inflating at a bit position in the middle of a + byte. The provided bits will be used before any bytes are used from + next_in. This function should be used with raw inflate, before the first + inflate() call, after inflateInit2() or inflateReset(). It can also be used + after an inflate() return indicates the end of a deflate block or header + when using Z_BLOCK. bits must be less than or equal to 16, and that many of + the least significant bits of value will be inserted in the input. The + other bits in value can be non-zero, and will be ignored. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent, or if bits is out of range. If inflate was + in the middle of processing a header, trailer, or stored block lengths, then + it is possible for there to be only eight bits available in the bit buffer. + In that case, bits > 8 is considered out of range. However, when used as + outlined above, there will always be 16 bits available in the buffer for + insertion. As noted in its documentation above, inflate records the number + of bits in the bit buffer on return in data_type. 32 minus that is the + number of bits available for insertion. inflatePrime does not update + data_type with the new number of bits in buffer. +*/ + +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) The extra, name, and comment pointers + much each be either Z_NULL or point to space to store that information from + the header. If extra is not Z_NULL, then extra_max contains the maximum + number of bytes that can be written to extra. Once done is true, extra_len + contains the actual extra field length, and extra contains the extra field, + or that field truncated if extra_max is less than extra_len. If name is not + Z_NULL, then up to name_max characters, including the terminating zero, are + written there. If comment is not Z_NULL, then up to comm_max characters, + including the terminating zero, are written there. The application can tell + that the name or comment did not fit in the provided space by the absence of + a terminating zero. If any of extra, name, or comment are not present in + the header, then that field's pointer is set to Z_NULL. This allows the use + of deflateSetHeader() with the returned structure to duplicate the header. + Note that if those fields initially pointed to allocated memory, then the + application will need to save them elsewhere so that they can be eventually + freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); + +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (all zeros is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() is not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + 27: 0 = gzprintf() present, 1 = not -- 1 means gzprintf() returns an error + + Remainder: + 28-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. The _z versions of the functions use the size_t + type for lengths. Note that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT compress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); +ZEXTERN int ZEXPORT compress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen, + int level); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); +ZEXTERN z_size_t ZEXPORT compressBound_z(z_size_t sourceLen); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT uncompress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. On entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) On exit, *destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); +ZEXTERN int ZEXPORT uncompress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. 'T' cannot be + used to force transparent reading. Transparent reading is automatically + performed if there is no gzip header at the start. Transparent reading can + be disabled with the 'G' option, which will instead return an error if there + is no gzip header. 'N' will open the file in non-blocking mode. + + 'a' can be used instead of 'w' to request that the gzip stream that will + be written be appended to the file. '+' will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + 'x' when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of 'e' when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. Note that if 'N' is in mode for non-blocking, the + open() itself can fail in order to not block. In that case gzopen() will + return NULL and errno will be EAGAIN or ENONBLOCK. The call to gzopen() can + then be re-tried. If the application would like to block on opening the + file, then it can use open() without O_NONBLOCK, and then gzdopen() with the + resulting file descriptor and 'N' in the mode, which will set it to non- + blocking. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. An + 'e' in mode will set fd's flag to close the file on an execve() call. An 'N' + in mode will set fd's non-blocking flag. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzread() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. If some data was read before an error, then that data is + returned until exhausted, after which the next call will signal the error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as that of fread() implementations in common libraries. This + could result in data loss if used with size != 1 when reading a concurrently + written file or a non-blocking file. In that case, use size == 1 or gzread() + instead. +*/ + +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written, or 0 in case of error or + if len is 0. If the write destination is non-blocking, then gzwrite() may + return a number of bytes written that is not 0 and less than len. + + If len does not fit in an int, then 0 is returned and nothing is written. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. + + If writing a concurrently read file or a non-blocking file with size != 1, + a partial item could be written, with no way of knowing how much of it was + not written, resulting in data loss. In that case, use size == 1 or + gzwrite() instead. +*/ + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); +#else +ZEXTERN int ZEXPORTVA gzprintf(); +#endif +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. + + In that last case, there may also be a buffer overflow with unpredictable + consequences, which is possible only if zlib was compiled with the insecure + functions sprintf() or vsprintf(), because the secure snprintf() and + vsnprintf() functions were not available. That would only be the case for + a non-ANSI C compiler. zlib may have been built without gzprintf() because + secure functions were not available and having gzprintf() be insecure was + not an option, in which case, gzprintf() returns Z_STREAM_ERROR. All of + these possibilities can be determined using zlibCompileFlags(). + + If a Z_BUF_ERROR is returned, then nothing was written due to a stall on + the non-blocking write destination. +*/ + +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. + The number of characters written may be less than the length of the string + if the write destination is non-blocking. + + If the length of the string does not fit in an int, then -1 is returned + and nothing is written. +*/ + +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If some data was read before an error, + then that data is returned until exhausted, after which the next call will + return NULL to signal the error. + + gzgets can be used on a file being concurrently written, and on a non- + blocking device, both as for gzread(). However lines may be broken in the + middle, leaving it up to the application to reassemble them as needed. +*/ + +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc(gzFile file); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 in + case of end of file or error. If some data was read before an error, then + that data is returned until exhausted, after which the next call will return + -1 to signal the error. + + This is implemented as a macro for speed. As such, it does not do all of + the checking the other functions do. I.e. it does not check to see if file + is NULL, nor whether the structure file points to has been clobbered or not. + + gzgetc can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzgetc() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. +*/ + +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). + + gzungetc(-1, file) will force any pending seek to execute. Then gztell() + will report the position, even if the requested seek reached end of file. + This can be used to determine the number of uncompressed bytes in a gzip + file without having to read it into a buffer. +*/ + +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. For reading or writing, any actual seeking is deferred + until the next read or write operation, or close operation when writing. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind(gzFile file); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof(gzFile file); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect(gzFile file); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). If the input is being written concurrently or the device is non- + blocking, then gzdirect() may give a different answer once four bytes of + input have been accumulated, which is what is needed to confirm or deny a + gzip header. Before this, gzdirect() will return true (1). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose(gzFile file); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); +/* + Return the error message for the last error which occurred on file. + If errnum is not NULL, *errnum is set to zlib error number. If an error + occurred in the file system and not in the compression library, *errnum is + set to Z_ERRNO and the application may consult errno to get the exact error + code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr(gzFile file); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); +/* + Same as adler32(), but with a size_t length. Note that a long is 32 bits + on Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); +/* + Same as crc32(), but with a size_t length. Note that a long is 32 bits on + Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. len2 must be non-negative, otherwise zero is returned. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). len2 must be non-negative, otherwise zero is returned. +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/include/zopfli.h b/app/src/main/cpp/third_party/pdf-android/x86_64/include/zopfli.h new file mode 100644 index 0000000..c079662 --- /dev/null +++ b/app/src/main/cpp/third_party/pdf-android/x86_64/include/zopfli.h @@ -0,0 +1,94 @@ +/* +Copyright 2011 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: lode.vandevenne@gmail.com (Lode Vandevenne) +Author: jyrki.alakuijala@gmail.com (Jyrki Alakuijala) +*/ + +#ifndef ZOPFLI_ZOPFLI_H_ +#define ZOPFLI_ZOPFLI_H_ + +#include +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Options used throughout the program. +*/ +typedef struct ZopfliOptions { + /* Whether to print output */ + int verbose; + + /* Whether to print more detailed output */ + int verbose_more; + + /* + Maximum amount of times to rerun forward and backward pass to optimize LZ77 + compression cost. Good values: 10, 15 for small files, 5 for files over + several MB in size or it will be too slow. + */ + int numiterations; + + /* + If true, splits the data in multiple deflate blocks with optimal choice + for the block boundaries. Block splitting gives better compression. Default: + true (1). + */ + int blocksplitting; + + /* + No longer used, left for compatibility. + */ + int blocksplittinglast; + + /* + Maximum amount of blocks to split into (0 for unlimited, but this can give + extreme results that hurt compression on some files). Default value: 15. + */ + int blocksplittingmax; +} ZopfliOptions; + +/* Initializes options with default values. */ +void ZopfliInitOptions(ZopfliOptions* options); + +/* Output format */ +typedef enum { + ZOPFLI_FORMAT_GZIP, + ZOPFLI_FORMAT_ZLIB, + ZOPFLI_FORMAT_DEFLATE +} ZopfliFormat; + +/* +Compresses according to the given output format and appends the result to the +output. + +options: global program options +output_type: the output format to use +out: pointer to the dynamic output array to which the result is appended. Must + be freed after use +outsize: pointer to the dynamic output array size +*/ +void ZopfliCompress(const ZopfliOptions* options, ZopfliFormat output_type, + const unsigned char* in, size_t insize, + unsigned char** out, size_t* outsize); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ZOPFLI_ZOPFLI_H_ */ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libjpeg.a b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libjpeg.a new file mode 100644 index 0000000..17fb897 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libjpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libqpdf.a b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libqpdf.a new file mode 100644 index 0000000..cd72057 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libqpdf.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libturbojpeg.a b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libturbojpeg.a new file mode 100644 index 0000000..61da4a4 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libturbojpeg.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libz.a b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libz.a new file mode 100644 index 0000000..f9966c1 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libz.a differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libz.so b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libz.so new file mode 100644 index 0000000..c8e3763 Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libz.so differ diff --git a/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libzopfli.a b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libzopfli.a new file mode 100644 index 0000000..b94f2fa Binary files /dev/null and b/app/src/main/cpp/third_party/pdf-android/x86_64/lib/libzopfli.a differ diff --git a/app/src/main/cpp/video_compressor.cpp b/app/src/main/cpp/video_compressor.cpp index 27292d9..d49d97e 100644 --- a/app/src/main/cpp/video_compressor.cpp +++ b/app/src/main/cpp/video_compressor.cpp @@ -48,6 +48,7 @@ extern "C" { struct FdAvio { int fd = -1; + bool can_read = false; uint8_t *buffer = nullptr; AVIOContext *ctx = nullptr; }; @@ -149,12 +150,53 @@ static int64_t fd_seek(void *opaque, int64_t offset, int whence) { return static_cast(ret); } + +static bool fd_supports_readback(int original_fd) { + if (original_fd < 0) { + return false; + } + + int test_fd = dup(original_fd); + if (test_fd < 0) { + return false; + } + + off64_t current = lseek64(test_fd, 0, SEEK_CUR); + if (current < 0) { + close(test_fd); + return false; + } + + uint8_t one_byte = 0; + errno = 0; + ssize_t ret = read(test_fd, &one_byte, 1); + int saved_errno = errno; + + // Kembalikan posisi supaya pengecekan ini tidak mengubah state FD. + lseek64(test_fd, current, SEEK_SET); + close(test_fd); + + if (ret >= 0) { + return true; + } + + // EBADF = FD write-only, tidak bisa dipakai untuk proses faststart. + if (saved_errno == EBADF) { + return false; + } + + // Error lain tetap dianggap tidak aman untuk readback. + return false; +} + static FdAvio *create_fd_avio(int original_fd, bool write_mode) { if (original_fd < 0) { errno = EBADF; return nullptr; } + const bool can_read = !write_mode || fd_supports_readback(original_fd); + int owned_fd = dup(original_fd); if (owned_fd < 0) { return nullptr; @@ -177,6 +219,7 @@ static FdAvio *create_fd_avio(int original_fd, bool write_mode) { FdAvio *fio = new FdAvio(); fio->fd = owned_fd; + fio->can_read = can_read; fio->buffer = static_cast(av_malloc(buffer_size)); if (!fio->buffer) { @@ -191,7 +234,7 @@ static FdAvio *create_fd_avio(int original_fd, bool write_mode) { buffer_size, write_mode ? 1 : 0, fio, - write_mode ? nullptr : fd_read_packet, + can_read ? fd_read_packet : nullptr, write_mode ? fd_write_packet : nullptr, fd_seek ); @@ -547,6 +590,31 @@ static bool is_audio_copy_supported_in_mp4(enum AVCodecID codec_id) { codec_id == AV_CODEC_ID_ALAC; } +static AVStream *find_first_audio_stream(AVFormatContext *fmt_ctx, int video_stream_index, int *audio_index) { + if (audio_index) { + *audio_index = -1; + } + + if (!fmt_ctx) { + return nullptr; + } + + for (unsigned int i = 0; i < fmt_ctx->nb_streams; ++i) { + if (static_cast(i) == video_stream_index) continue; + + AVStream *stream = fmt_ctx->streams[i]; + if (!stream || !stream->codecpar) continue; + if (stream->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) continue; + + if (audio_index) { + *audio_index = static_cast(i); + } + return stream; + } + + return nullptr; +} + static void get_audio_ch_layout_compat(AVChannelLayout *dst, AVCodecContext *ctx) { if (!dst) return; @@ -745,18 +813,20 @@ static int encode_and_write(AVCodecContext *enc_ctx, } } -int compress_video_fd_impl(JNIEnv *env, - int input_fd, - int output_fd, - int target_short_side, - int input_rotation_degrees, - int crf, - int video_bitrate, - const std::string &encoder_name, - const std::string &preset, - const std::string &audio_mode, - int audio_bitrate, - jobject callback) { +static int compress_video_core_impl(JNIEnv *env, + int input_fd, + int output_fd, + const char *output_path, + bool output_to_path, + int target_short_side, + int input_rotation_degrees, + int crf, + int video_bitrate, + const std::string &encoder_name, + const std::string &preset, + const std::string &audio_mode, + int audio_bitrate, + jobject callback) { FdAvio *input_io = nullptr; FdAvio *output_io = nullptr; @@ -793,6 +863,7 @@ int compress_video_fd_impl(JNIEnv *env, bool audio_transcode_aac = audio_mode == "aac"; bool audio_copy_original = audio_mode == "copy"; bool audio_mute = audio_mode == "mute"; + bool can_use_faststart = false; callback_progress(env, callback, 0, "Open input"); @@ -867,21 +938,43 @@ int compress_video_fd_impl(JNIEnv *env, callback_progress(env, callback, 2, "Prepare output"); - ret = avformat_alloc_output_context2(&out_fmt_ctx, nullptr, "mp4", nullptr); + ret = avformat_alloc_output_context2( + &out_fmt_ctx, + nullptr, + "mp4", + output_to_path ? output_path : nullptr + ); if (ret < 0 || !out_fmt_ctx) { LOGE("avformat_alloc_output_context2 failed: %s", av_err_to_string(ret).c_str()); goto cleanup; } - output_io = create_fd_avio(output_fd, true); - if (!output_io) { - ret = AVERROR(errno ? errno : EIO); - LOGE("create_fd_avio output failed: %s", av_err_to_string(ret).c_str()); - goto cleanup; - } + if (output_to_path) { + if (!output_path || output_path[0] == '\0') { + ret = AVERROR(EINVAL); + LOGE("output path is empty"); + goto cleanup; + } - out_fmt_ctx->pb = output_io->ctx; - out_fmt_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; + ret = avio_open(&out_fmt_ctx->pb, output_path, AVIO_FLAG_WRITE); + if (ret < 0) { + LOGE("avio_open output path failed: %s", av_err_to_string(ret).c_str()); + goto cleanup; + } + + LOGD("Output uses normal file path, faststart is safe: %s", output_path); + } else { + output_io = create_fd_avio(output_fd, true); + if (!output_io) { + ret = AVERROR(errno ? errno : EIO); + LOGE("create_fd_avio output failed: %s", av_err_to_string(ret).c_str()); + goto cleanup; + } + + out_fmt_ctx->pb = output_io->ctx; + out_fmt_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; + LOGD("Output uses custom FD AVIO, faststart will be disabled"); + } stream_mapping.assign(in_fmt_ctx->nb_streams, -1); @@ -1081,6 +1174,21 @@ int compress_video_fd_impl(JNIEnv *env, } } + if (audio_copy_original) { + int detected_audio_index = -1; + AVStream *detected_audio = find_first_audio_stream(in_fmt_ctx, video_stream_index, &detected_audio_index); + + if (detected_audio && detected_audio->codecpar && + !is_audio_copy_supported_in_mp4(detected_audio->codecpar->codec_id)) { + // MOV/QuickTime sering membawa PCM atau codec audio lain yang tidak aman dicopy ke MP4. + // Daripada hasil output tanpa audio, otomatis transcode ke AAC. + LOGD("Audio copy not safe for MP4 codec_id=%d, auto transcode to AAC", detected_audio->codecpar->codec_id); + callback_progress(env, callback, 0, "Audio original tidak kompatibel MP4, otomatis AAC..."); + audio_copy_original = false; + audio_transcode_aac = true; + } + } + if (audio_mute) { LOGD("Audio mode: mute"); } else if (audio_transcode_aac) { @@ -1221,6 +1329,26 @@ int compress_video_fd_impl(JNIEnv *env, } } + // Setara CLI FFmpeg: + // -movflags +faststart + // + // Faststart hanya diaktifkan pada output path file biasa. + // Jangan aktifkan faststart pada custom AVIO FD karena MOV muxer bisa gagal + // di av_write_trailer() dengan error "No such file or directory". + can_use_faststart = output_to_path; + + if (can_use_faststart && out_fmt_ctx && out_fmt_ctx->priv_data) { + ret = av_opt_set(out_fmt_ctx->priv_data, "movflags", "+faststart", 0); + if (ret < 0) { + LOGD("movflags +faststart not applied: %s", av_err_to_string(ret).c_str()); + ret = 0; + } else { + LOGD("movflags +faststart enabled"); + } + } else { + LOGD("movflags +faststart skipped: output is custom FD AVIO"); + } + ret = avformat_write_header(out_fmt_ctx, nullptr); if (ret < 0) { LOGE("avformat_write_header failed: %s", av_err_to_string(ret).c_str()); @@ -1530,7 +1658,12 @@ cleanup: if (enc_ctx) avcodec_free_context(&enc_ctx); if (out_fmt_ctx) { - out_fmt_ctx->pb = nullptr; + if (output_to_path && out_fmt_ctx->pb) { + avio_closep(&out_fmt_ctx->pb); + } else { + out_fmt_ctx->pb = nullptr; + } + avformat_free_context(out_fmt_ctx); out_fmt_ctx = nullptr; } @@ -1545,3 +1678,64 @@ cleanup: return ret < 0 ? ret : 0; } + +int compress_video_fd_impl(JNIEnv *env, + int input_fd, + int output_fd, + int target_short_side, + int input_rotation_degrees, + int crf, + int video_bitrate, + const std::string &encoder_name, + const std::string &preset, + const std::string &audio_mode, + int audio_bitrate, + jobject callback) { + return compress_video_core_impl( + env, + input_fd, + output_fd, + nullptr, + false, + target_short_side, + input_rotation_degrees, + crf, + video_bitrate, + encoder_name, + preset, + audio_mode, + audio_bitrate, + callback + ); +} + +int compress_video_fd_to_path_impl(JNIEnv *env, + int input_fd, + const std::string &output_path, + int target_short_side, + int input_rotation_degrees, + int crf, + int video_bitrate, + const std::string &encoder_name, + const std::string &preset, + const std::string &audio_mode, + int audio_bitrate, + jobject callback) { + return compress_video_core_impl( + env, + input_fd, + -1, + output_path.c_str(), + true, + target_short_side, + input_rotation_degrees, + crf, + video_bitrate, + encoder_name, + preset, + audio_mode, + audio_bitrate, + callback + ); +} + diff --git a/app/src/main/cpp/video_compressor.h b/app/src/main/cpp/video_compressor.h index f1c14a4..9ba0d7e 100644 --- a/app/src/main/cpp/video_compressor.h +++ b/app/src/main/cpp/video_compressor.h @@ -15,3 +15,16 @@ int compress_video_fd_impl(JNIEnv *env, const std::string &audio_mode, int audio_bitrate, jobject callback); + +int compress_video_fd_to_path_impl(JNIEnv *env, + int input_fd, + const std::string &output_path, + int target_short_side, + int input_rotation_degrees, + int crf, + int video_bitrate, + const std::string &encoder_name, + const std::string &preset, + const std::string &audio_mode, + int audio_bitrate, + jobject callback); diff --git a/app/src/main/java/com/kikyps/kcompressor/MainActivity.java b/app/src/main/java/com/kikyps/kcompressor/MainActivity.java index 1d81763..56cb6be 100644 --- a/app/src/main/java/com/kikyps/kcompressor/MainActivity.java +++ b/app/src/main/java/com/kikyps/kcompressor/MainActivity.java @@ -7,6 +7,8 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; import android.media.MediaMetadataRetriever; import android.media.MediaExtractor; import android.media.MediaFormat; @@ -17,10 +19,14 @@ import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.provider.OpenableColumns; +import android.view.Gravity; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.PopupWindow; import android.widget.SeekBar; import android.widget.Spinner; import android.widget.TextView; @@ -50,6 +56,10 @@ public class MainActivity extends Activity { static final String EXTRA_AUDIO_MODE = "audio_mode"; static final String EXTRA_AUDIO_LABEL = "audio_label"; static final String EXTRA_AUDIO_BITRATE = "audio_bitrate"; + static final String EXTRA_INPUT_CONTAINER_LABEL = "input_container_label"; + static final String EXTRA_INPUT_VIDEO_CODEC_LABEL = "input_video_codec_label"; + static final String EXTRA_INPUT_AUDIO_CODEC_LABEL = "input_audio_codec_label"; + static final String EXTRA_SOURCE_NOTE = "source_note"; static final String EXTRA_VIDEO_BITRATE = "video_bitrate"; static final String EXTRA_VIDEO_BITRATE_LABEL = "video_bitrate_label"; static final String EXTRA_JOB_TYPE = "job_type"; @@ -95,6 +105,7 @@ public class MainActivity extends Activity { private TextView txtCrfValue; private TextView txtCompressionSummary; private TextView txtSettingsToggle; + private ImageButton btnCodecHelp; private View layoutCompressionSettings; private View layoutAdvancedSettings; private Button btnPick; @@ -105,6 +116,7 @@ public class MainActivity extends Activity { private TextView txtImageQualityValue; private TextView txtImageCompressionSummary; private TextView txtImageSettingsToggle; + private ImageButton btnImageFormatHelp; private View layoutImageSettings; private View layoutImageAdvancedSettings; private Button btnPickImage; @@ -187,9 +199,12 @@ public class MainActivity extends Activity { int trackCount; float frameRate; boolean hasAudio; + boolean movContainer; String containerMime; String videoMime; String audioMime; + String displayName; + String sourceNote; } private static final class ResolutionOption { @@ -274,6 +289,7 @@ public class MainActivity extends Activity { txtCrfValue = findViewById(R.id.txtCrfValue); txtCompressionSummary = findViewById(R.id.txtCompressionSummary); txtSettingsToggle = findViewById(R.id.txtSettingsToggle); + btnCodecHelp = findViewById(R.id.btnCodecHelp); layoutCompressionSettings = findViewById(R.id.layoutCompressionSettings); layoutAdvancedSettings = findViewById(R.id.layoutAdvancedSettings); btnPick = findViewById(R.id.btnPick); @@ -287,6 +303,7 @@ public class MainActivity extends Activity { txtImageQualityValue = findViewById(R.id.txtImageQualityValue); txtImageCompressionSummary = findViewById(R.id.txtImageCompressionSummary); txtImageSettingsToggle = findViewById(R.id.txtImageSettingsToggle); + btnImageFormatHelp = findViewById(R.id.btnImageFormatHelp); layoutImageSettings = findViewById(R.id.layoutImageSettings); layoutImageAdvancedSettings = findViewById(R.id.layoutImageAdvancedSettings); btnPickImage = findViewById(R.id.btnPickImage); @@ -320,6 +337,8 @@ public class MainActivity extends Activity { btnPickImage.setOnClickListener(v -> openImagePicker()); txtSettingsToggle.setOnClickListener(v -> setSettingsExpanded(!settingsExpanded)); txtImageSettingsToggle.setOnClickListener(v -> setImageSettingsExpanded(!imageSettingsExpanded)); + btnCodecHelp.setOnClickListener(v -> showCodecOutputGuide()); + btnImageFormatHelp.setOnClickListener(v -> showImageFormatGuide()); btnCompress.setOnClickListener(v -> { if (inputUri == null) { @@ -562,6 +581,222 @@ public class MainActivity extends Activity { } + private void showCodecOutputGuide() { + Object selected = spCodec != null ? spCodec.getSelectedItem() : null; + String title = "Codec Output"; + String message = "Pilih codec sesuai kebutuhan hasil video."; + String recommendation = "Rekomendasi umum: H.264 Hardware GPU jika tersedia. Fallback paling kompatibel: H.264 CPU."; + + if (selected instanceof CodecOption) { + CodecOption option = (CodecOption) selected; + title = option.label; + + if ("libx264".equals(option.encoderName)) { + message = + "H.264 CPU memakai libx264. Cocok untuk kompatibilitas maksimal, hasil stabil, dan ukuran file bagus.\n\n" + + "Kelebihan:\n" + + "• Paling aman untuk WhatsApp, Telegram, Instagram, galeri HP, dan hampir semua player.\n" + + "• CRF dan preset bisa dikontrol.\n\n" + + "Kekurangan:\n" + + "• Lebih lambat dan lebih boros CPU dibanding Hardware GPU."; + recommendation = "Recommended choice: gunakan ini jika ingin hasil paling aman dibuka di banyak device/app."; + } else if ("libx265".equals(option.encoderName)) { + message = + "H.265 CPU memakai libx265. Cocok jika ingin ukuran lebih kecil dari H.264 dengan kualitas mirip.\n\n" + + "Kelebihan:\n" + + "• Efisiensi kompresi lebih baik dari H.264.\n" + + "• Bagus untuk arsip pribadi atau video resolusi tinggi.\n\n" + + "Kekurangan:\n" + + "• Encode lebih berat/lambat.\n" + + "• Kompatibilitas tidak seaman H.264, terutama untuk beberapa aplikasi sosial."; + recommendation = "Recommended choice: gunakan untuk simpan pribadi atau device modern, bukan untuk kompatibilitas paling luas."; + } else if ("h264_mediacodec".equals(option.encoderName)) { + message = + "H.264 Hardware GPU memakai encoder MediaCodec bawaan device. Ini paling praktis untuk proses cepat.\n\n" + + "Kelebihan:\n" + + "• Encode lebih cepat.\n" + + "• Lebih hemat baterai dibanding CPU.\n" + + "• Format H.264 tetap sangat kompatibel.\n\n" + + "Kekurangan:\n" + + "• Kontrol kualitas memakai bitrate, bukan CRF.\n" + + "• Kualitas tergantung hardware encoder HP."; + recommendation = "Recommended choice: pilihan terbaik untuk penggunaan harian jika tersedia."; + } else if ("hevc_mediacodec".equals(option.encoderName)) { + message = + "H.265 Hardware GPU memakai encoder HEVC MediaCodec bawaan device. Cocok untuk ukuran kecil dan proses cepat jika device mendukung.\n\n" + + "Kelebihan:\n" + + "• Lebih efisien dari H.264.\n" + + "• Lebih cepat dari H.265 CPU.\n\n" + + "Kekurangan:\n" + + "• Tidak semua HP mendukung encode H.265.\n" + + "• Beberapa aplikasi/player lama mungkin tidak kompatibel."; + recommendation = "Recommended choice: gunakan untuk device modern dan penyimpanan pribadi; untuk share universal tetap H.264."; + } + } + + showGuidePopup(spCodec != null ? spCodec : btnCodecHelp, title, message, recommendation); + } + + private void showImageFormatGuide() { + Object selected = spImageFormat != null ? spImageFormat.getSelectedItem() : null; + String title = "Format Output"; + String message = "Pilih format gambar sesuai kebutuhan ukuran, kualitas, dan kompatibilitas."; + String recommendation = "Rekomendasi umum: JPEG/MozJPEG untuk foto, PNG TinyPNG Style untuk PNG transparan/ilustrasi, WebP untuk ukuran kecil."; + + if (selected instanceof ImageFormatOption) { + ImageFormatOption option = (ImageFormatOption) selected; + title = option.label; + + if ("jpeg".equals(option.format)) { + message = + "JPEG / MozJPEG cocok untuk foto, dokumentasi, dan gambar tanpa transparansi.\n\n" + + "Kelebihan:\n" + + "• Kompatibilitas paling luas.\n" + + "• Ukuran kecil untuk foto.\n" + + "• MozJPEG biasanya menghasilkan JPEG lebih optimal dari encoder biasa.\n\n" + + "Kekurangan:\n" + + "• Lossy, kualitas turun jika quality terlalu kecil.\n" + + "• Tidak mendukung transparansi."; + recommendation = "Recommended choice: pilih ini untuk foto biasa, upload, dan share universal."; + } else if ("png_lossless".equals(option.format)) { + message = + "PNG Lossless / OxiPNG menyimpan gambar tanpa penurunan kualitas visual.\n\n" + + "Kelebihan:\n" + + "• Kualitas tetap asli.\n" + + "• Mendukung transparansi.\n" + + "• Cocok untuk logo, screenshot UI, teks, line-art, dan icon.\n\n" + + "Kekurangan:\n" + + "• Ukuran bisa lebih besar dari format lossy."; + recommendation = "Recommended choice: pilih ini jika kualitas harus tetap utuh atau gambar punya transparansi penting."; + } else if ("png_lossy".equals(option.format)) { + message = + "PNG TinyPNG Style berarti PNG dikurangi jumlah warnanya memakai palette quantization, mirip konsep TinyPNG.\n\n" + + "Tujuannya:\n" + + "• Ukuran PNG jauh lebih kecil.\n" + + "• Transparansi tetap bisa dipertahankan.\n\n" + + "Cocok untuk:\n" + + "• Logo, stiker, ilustrasi, screenshot sederhana, undangan digital, dan gambar dengan warna tidak terlalu kompleks.\n\n" + + "Kekurangan:\n" + + "• Lossy. Pada foto atau gradient halus bisa muncul banding/perubahan warna."; + recommendation = "Recommended choice: pilih ini untuk mengecilkan PNG dengan ukuran besar tanpa mengubah ke JPEG."; + } else if ("webp".equals(option.format)) { + message = + "WebP Lossy cocok untuk ukuran file kecil dengan kualitas visual masih bagus.\n\n" + + "Kelebihan:\n" + + "• Biasanya lebih kecil dari JPEG pada kualitas mirip.\n" + + "• Bisa bagus untuk web, katalog, preview, dan penyimpanan ringan.\n\n" + + "Kekurangan:\n" + + "• Kompatibilitas sangat baik di Android modern, tetapi tidak seuniversal JPEG untuk semua aplikasi lama."; + recommendation = "Recommended choice: pilih ini jika prioritas ukuran kecil dan targetnya Android/web modern."; + } else if ("webp_lossless".equals(option.format)) { + message = + "WebP Lossless menyimpan gambar tanpa kehilangan kualitas, sering lebih kecil dari PNG untuk beberapa jenis gambar.\n\n" + + "Kelebihan:\n" + + "• Lossless.\n" + + "• Mendukung transparansi.\n" + + "• Bisa lebih kecil dari PNG.\n\n" + + "Kekurangan:\n" + + "• Kompatibilitas tidak seluas PNG/JPEG di beberapa aplikasi lama."; + recommendation = "Recommended choice: pilih ini untuk arsip lossless modern dengan transparansi."; + } else if ("avif".equals(option.format)) { + message = + "AVIF cocok untuk kompresi gambar sangat efisien dengan ukuran kecil.\n\n" + + "Kelebihan:\n" + + "• Ukuran sangat kecil untuk kualitas bagus.\n" + + "• Cocok untuk penyimpanan modern dan web modern.\n\n" + + "Kekurangan:\n" + + "• Encode lebih lambat.\n" + + "• Kompatibilitas aplikasi lama belum seaman JPEG/WebP."; + recommendation = "Recommended choice: pilih ini untuk ukuran paling kecil jika target device/app sudah modern."; + } + } + + showGuidePopup(spImageFormat != null ? spImageFormat : btnImageFormatHelp, title, message, recommendation); + } + + private void showGuidePopup(View anchor, String title, String message, String recommendation) { + if (anchor == null) { + return; + } + + final int margin = dp(14); + final int popupWidth = Math.max(dp(280), getResources().getDisplayMetrics().widthPixels - (margin * 2)); + + LinearLayout root = new LinearLayout(this); + root.setOrientation(LinearLayout.VERTICAL); + root.setPadding(margin, 0, margin, margin); + root.setBackgroundColor(Color.TRANSPARENT); + + TextView arrow = new TextView(this); + arrow.setText("▲"); + arrow.setTextColor(0xFF111827); + arrow.setTextSize(20f); + arrow.setGravity(Gravity.CENTER); + root.addView(arrow, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + )); + + LinearLayout card = new LinearLayout(this); + card.setOrientation(LinearLayout.VERTICAL); + card.setPadding(dp(16), dp(14), dp(16), dp(14)); + card.setBackgroundColor(0xFF111827); + + TextView titleView = new TextView(this); + titleView.setText(title); + titleView.setTextColor(0xFFFFFFFF); + titleView.setTextSize(15f); + titleView.setTypeface(null, android.graphics.Typeface.BOLD); + card.addView(titleView); + + TextView messageView = new TextView(this); + messageView.setText(message); + messageView.setTextColor(0xFFD1D5DB); + messageView.setTextSize(13f); + messageView.setLineSpacing(dp(2), 1.0f); + LinearLayout.LayoutParams msgParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + msgParams.topMargin = dp(8); + card.addView(messageView, msgParams); + + TextView recView = new TextView(this); + recView.setText(recommendation); + recView.setTextColor(0xFF22C55E); + recView.setTextSize(13f); + recView.setTypeface(null, android.graphics.Typeface.BOLD); + recView.setLineSpacing(dp(2), 1.0f); + LinearLayout.LayoutParams recParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + recParams.topMargin = dp(10); + card.addView(recView, recParams); + + root.addView(card, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + )); + + PopupWindow popup = new PopupWindow( + root, + popupWidth, + LinearLayout.LayoutParams.WRAP_CONTENT, + true + ); + + popup.setOutsideTouchable(true); + popup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + popup.setElevation(dp(8)); + + popup.showAsDropDown(anchor, -margin, dp(2)); + } + + private int dp(int value) { + return Math.round(value * getResources().getDisplayMetrics().density); + } + private void setupSpinners() { ArrayList codecItems = buildVideoCodecOptions(); @@ -1053,6 +1288,16 @@ public class MainActivity extends Activity { intent.setType("video/*"); } + // Tambahan eksplisit agar .mov / QuickTime lebih mudah muncul di picker provider tertentu. + intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{ + "video/*", + "video/mp4", + "video/quicktime", + "video/x-m4v", + "video/3gpp", + "video/x-matroska", + "video/avi" + }); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); try { @@ -1102,8 +1347,11 @@ public class MainActivity extends Activity { currentVideoInfo = readVideoInfo(inputUri); setResolutionOptions(currentVideoInfo); selectBestCodecForSelectedVideo(currentVideoInfo); + applyRecommendedSettingsForSelectedVideo(currentVideoInfo); - txtSelected.setText("Video dipilih"); + txtSelected.setText(currentVideoInfo != null && currentVideoInfo.movContainer + ? "Video MOV/QuickTime dipilih" + : "Video dipilih"); txtVideoInfo.setText(makeVideoInfoText(currentVideoInfo, inputUri)); layoutCompressionSettings.setVisibility(View.VISIBLE); btnCompress.setVisibility(View.VISIBLE); @@ -1212,11 +1460,13 @@ public class MainActivity extends Activity { retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION), 0L); info.bitrate = parseIntSafe( retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE), 0); - info.containerMime = safeString( + info.containerMime = normalizeVideoMime(safeString( retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE), getContentResolver().getType(uri) - ); + )); info.fileSizeBytes = readOriginalFileSize(uri); + info.displayName = readDisplayName(uri); + info.movContainer = isMovQuickTimeVideo(info.containerMime, info.displayName, uri); if (info.rotation == 90 || info.rotation == 270) { info.displayWidth = info.codedHeight; @@ -1230,6 +1480,7 @@ public class MainActivity extends Activity { info.longSide = Math.max(info.displayWidth, info.displayHeight); readMediaExtractorInfo(uri, info); + applyVideoSourceNote(info); } catch (Throwable t) { info.codedWidth = 0; @@ -1245,9 +1496,12 @@ public class MainActivity extends Activity { info.trackCount = 0; info.frameRate = 0f; info.hasAudio = false; - info.containerMime = safeString(null, getContentResolver().getType(uri)); + info.containerMime = normalizeVideoMime(safeString(null, getContentResolver().getType(uri))); + info.displayName = readDisplayName(uri); + info.movContainer = isMovQuickTimeVideo(info.containerMime, info.displayName, uri); info.videoMime = null; info.audioMime = null; + applyVideoSourceNote(info); } finally { try { retriever.release(); @@ -1427,6 +1681,148 @@ public class MainActivity extends Activity { } + private void applyRecommendedSettingsForSelectedVideo(VideoInfo info) { + if (info == null) { + updateCompressionSummary(); + return; + } + + if (info.movContainer) { + // MOV/QuickTime sering berisi PCM/ALAC/ProRes/MJPEG. + // Output app tetap MP4, jadi pilihan paling aman untuk kompatibilitas adalah: + // video -> H.264, audio -> AAC. + selectCodecIfAvailable("h264_mediacodec", "libx264"); + selectAudioMode("aac", 160000); + toast("MOV terdeteksi: output otomatis diset H.264 + AAC agar kompatibel MP4"); + } else if (shouldForceAacForMp4(info.audioMime)) { + selectAudioMode("aac", 128000); + } + + syncAdvancedVideoSettingsForSelectedCodec(); + updateCompressionSummary(); + } + + private boolean selectCodecIfAvailable(String preferredEncoder, String fallbackEncoder) { + if (spCodec == null || spCodec.getAdapter() == null) { + return false; + } + + int preferredIndex = findCodecIndexByEncoder(preferredEncoder); + if (preferredIndex >= 0) { + spCodec.setSelection(preferredIndex); + return true; + } + + int fallbackIndex = findCodecIndexByEncoder(fallbackEncoder); + if (fallbackIndex >= 0) { + spCodec.setSelection(fallbackIndex); + return true; + } + + return false; + } + + private boolean selectAudioMode(String mode, int bitrate) { + if (spAudio == null || spAudio.getAdapter() == null || mode == null) { + return false; + } + + for (int i = 0; i < spAudio.getAdapter().getCount(); i++) { + Object item = spAudio.getAdapter().getItem(i); + if (item instanceof AudioOption) { + AudioOption option = (AudioOption) item; + if (mode.equals(option.mode) && (bitrate <= 0 || option.bitrate == bitrate)) { + spAudio.setSelection(i); + return true; + } + } + } + + for (int i = 0; i < spAudio.getAdapter().getCount(); i++) { + Object item = spAudio.getAdapter().getItem(i); + if (item instanceof AudioOption && mode.equals(((AudioOption) item).mode)) { + spAudio.setSelection(i); + return true; + } + } + + return false; + } + + private void applyVideoSourceNote(VideoInfo info) { + if (info == null) { + return; + } + + if (info.movContainer) { + StringBuilder note = new StringBuilder("MOV/QuickTime → output MP4, rekomendasi H.264 + AAC"); + + if (shouldForceAacForMp4(info.audioMime)) { + note.append("; audio original tidak aman untuk copy MP4 sehingga ditranscode ke AAC"); + } + + String videoMime = info.videoMime != null ? info.videoMime.toLowerCase(Locale.US) : ""; + if (videoMime.contains("prores") || videoMime.contains("mjpeg") || videoMime.contains("jpeg") || videoMime.contains("png")) { + note.append("; codec video kamera/pro dapat dibaca jika decoder FFmpeg MOV lengkap aktif"); + } + + info.sourceNote = note.toString(); + return; + } + + if (shouldForceAacForMp4(info.audioMime)) { + info.sourceNote = "Audio original tidak aman untuk copy MP4, rekomendasi AAC"; + } else { + info.sourceNote = ""; + } + } + + private boolean isMovQuickTimeVideo(String mime, String displayName, Uri uri) { + String value = normalizeVideoMime(mime); + if ("video/quicktime".equals(value) || "video/x-quicktime".equals(value) || "video/x-m4v".equals(value)) { + return true; + } + + String name = displayName; + if ((name == null || name.length() == 0) && uri != null) { + name = String.valueOf(uri); + } + + if (name == null) { + return false; + } + + String lower = name.toLowerCase(Locale.US); + return lower.endsWith(".mov") || lower.endsWith(".qt") || lower.endsWith(".m4v"); + } + + private String normalizeVideoMime(String mime) { + if (mime == null) { + return ""; + } + + String value = mime.toLowerCase(Locale.US).trim(); + if ("video/quicktime".equals(value) || "video/x-quicktime".equals(value)) { + return "video/quicktime"; + } + if ("video/x-m4v".equals(value)) { + return "video/x-m4v"; + } + return value; + } + + private boolean shouldForceAacForMp4(String audioMime) { + if (audioMime == null || audioMime.length() == 0) { + return false; + } + + String value = audioMime.toLowerCase(Locale.US); + return !("audio/mp4a-latm".equals(value) || + "audio/aac".equals(value) || + "audio/mpeg".equals(value) || + "audio/alac".equals(value)); + } + private void readMediaExtractorInfo(Uri uri, VideoInfo info) { MediaExtractor extractor = new MediaExtractor(); @@ -1540,6 +1936,20 @@ public class MainActivity extends Activity { return "AV1 (" + mime + ")"; } + String lowerMime = mime.toLowerCase(Locale.US); + if (lowerMime.contains("prores")) { + return "Apple ProRes (" + mime + ")"; + } + if (lowerMime.contains("mjpeg") || lowerMime.contains("jpeg")) { + return "MJPEG (" + mime + ")"; + } + if (lowerMime.contains("png")) { + return "PNG Video (" + mime + ")"; + } + if (lowerMime.contains("qtrle")) { + return "QuickTime Animation / RLE (" + mime + ")"; + } + if ("audio/mp4a-latm".equalsIgnoreCase(mime)) { return "AAC (" + mime + ")"; } @@ -1552,6 +1962,15 @@ public class MainActivity extends Activity { return "Opus (" + mime + ")"; } + if ("audio/alac".equalsIgnoreCase(mime)) { + return "ALAC (" + mime + ")"; + } + + String audioLower = mime.toLowerCase(Locale.US); + if (audioLower.contains("pcm") || audioLower.contains("raw")) { + return "PCM / Raw Audio (" + mime + ")"; + } + return mime; } @@ -1610,6 +2029,12 @@ public class MainActivity extends Activity { String audioLabel = audioOption != null ? audioOption.label : "Original / Copy"; int audioBitrate = audioOption != null ? audioOption.bitrate : 0; + if (currentVideoInfo != null && currentVideoInfo.movContainer && shouldForceAacForMp4(currentVideoInfo.audioMime)) { + audioMode = "aac"; + audioLabel = "AAC 160 kbps (Auto MOV)"; + audioBitrate = 160000; + } + saveSettings(targetShortSide, crf); Intent intent = new Intent(this, ProcessingActivity.class); @@ -1627,6 +2052,10 @@ public class MainActivity extends Activity { intent.putExtra(EXTRA_AUDIO_MODE, audioMode); intent.putExtra(EXTRA_AUDIO_LABEL, audioLabel); intent.putExtra(EXTRA_AUDIO_BITRATE, audioBitrate); + intent.putExtra(EXTRA_INPUT_CONTAINER_LABEL, currentVideoInfo != null && currentVideoInfo.movContainer ? "MOV / QuickTime" : "Video"); + intent.putExtra(EXTRA_INPUT_VIDEO_CODEC_LABEL, currentVideoInfo != null ? formatCodecName(currentVideoInfo.videoMime) : ""); + intent.putExtra(EXTRA_INPUT_AUDIO_CODEC_LABEL, currentVideoInfo != null ? formatCodecName(currentVideoInfo.audioMime) : ""); + intent.putExtra(EXTRA_SOURCE_NOTE, currentVideoInfo != null ? currentVideoInfo.sourceNote : ""); startActivity(intent); } diff --git a/app/src/main/java/com/kikyps/kcompressor/NativeCompressor.java b/app/src/main/java/com/kikyps/kcompressor/NativeCompressor.java index f5ed48d..4fa1ce1 100644 --- a/app/src/main/java/com/kikyps/kcompressor/NativeCompressor.java +++ b/app/src/main/java/com/kikyps/kcompressor/NativeCompressor.java @@ -35,6 +35,59 @@ public final class NativeCompressor { ProgressCallback callback ); + /** + * Versi video temp-file path. + * + * Dipakai agar MP4 muxer bisa memakai -movflags +faststart dengan aman. + * Jangan memakai custom output FD untuk faststart karena MOV muxer dapat gagal + * di av_write_trailer() pada custom AVIO/ContentResolver FD. + */ + public static native int compressFdToPath( + int inputFd, + String outputPath, + int targetShortSide, + int inputRotationDegrees, + int crf, + int videoBitrate, + String encoderName, + String preset, + String audioMode, + int audioBitrate, + ProgressCallback callback + ); + + /** + * Wrapper kompatibilitas untuk caller lama yang belum membawa parameter: + * videoBitrate, audioMode, dan audioBitrate. + * + * Jangan jadikan ini native. Ini hanya forward ke signature native baru + * agar parameter JNI tidak bergeser dan tidak crash di GetStringUTFChars(). + */ + public static int compressFd( + int inputFd, + int outputFd, + int targetShortSide, + int inputRotationDegrees, + int crf, + String encoderName, + String preset, + ProgressCallback callback + ) { + return compressFd( + inputFd, + outputFd, + targetShortSide, + inputRotationDegrees, + crf, + 0, + encoderName, + preset, + "copy", + 0, + callback + ); + } + /** * outputFormat: * jpeg = MozJPEG/TurboJPEG output .jpg diff --git a/app/src/main/java/com/kikyps/kcompressor/ProcessingActivity.java b/app/src/main/java/com/kikyps/kcompressor/ProcessingActivity.java index 1d0602a..f2a3797 100644 --- a/app/src/main/java/com/kikyps/kcompressor/ProcessingActivity.java +++ b/app/src/main/java/com/kikyps/kcompressor/ProcessingActivity.java @@ -28,6 +28,8 @@ import android.widget.TextView; import android.widget.Toast; import java.io.File; +import java.io.FileInputStream; +import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -36,6 +38,10 @@ public class ProcessingActivity extends Activity { private static final long DIM_DELAY_MS = 10_000L; private static final float DIM_BRIGHTNESS = 0.01f; + private static final int COLOR_PROGRESS_SUCCESS = 0xFF22C55E; + private static final int COLOR_STATUS_NORMAL = 0xFFD1D5DB; + private static final float STATUS_TEXT_SIZE_NORMAL_SP = 15f; + private static final float STATUS_TEXT_SIZE_SUCCESS_SP = 34f; private CircleProgressView circleProgress; private TextView txtProcessingTitle; @@ -43,6 +49,7 @@ public class ProcessingActivity extends Activity { private TextView txtElapsed; private TextView txtConfig; private TextView txtOutput; + private View layoutOutputCard; private Button btnCancel; private Button btnShareVideo; private Button btnShareDoc; @@ -69,6 +76,10 @@ public class ProcessingActivity extends Activity { private String audioMode; private String audioLabel; private int audioBitrate; + private String inputContainerLabel; + private String inputVideoCodecLabel; + private String inputAudioCodecLabel; + private String sourceNote; private String inputMime; private String outputFormat; @@ -140,12 +151,16 @@ public class ProcessingActivity extends Activity { txtElapsed = findViewById(R.id.txtElapsed); txtConfig = findViewById(R.id.txtConfig); txtOutput = findViewById(R.id.txtOutput); + layoutOutputCard = findViewById(R.id.layoutOutputCard); btnCancel = findViewById(R.id.btnCancel); btnShareVideo = findViewById(R.id.btnShareVideo); btnShareDoc = findViewById(R.id.btnShareDoc); btnShareVideo.setVisibility(View.GONE); btnShareDoc.setVisibility(View.GONE); + if (layoutOutputCard != null) { + layoutOutputCard.setVisibility(View.GONE); + } readIntentExtras(); updateConfigCard(); @@ -185,6 +200,10 @@ public class ProcessingActivity extends Activity { audioMode = getIntent().getStringExtra(MainActivity.EXTRA_AUDIO_MODE); audioLabel = getIntent().getStringExtra(MainActivity.EXTRA_AUDIO_LABEL); audioBitrate = getIntent().getIntExtra(MainActivity.EXTRA_AUDIO_BITRATE, 0); + inputContainerLabel = getIntent().getStringExtra(MainActivity.EXTRA_INPUT_CONTAINER_LABEL); + inputVideoCodecLabel = getIntent().getStringExtra(MainActivity.EXTRA_INPUT_VIDEO_CODEC_LABEL); + inputAudioCodecLabel = getIntent().getStringExtra(MainActivity.EXTRA_INPUT_AUDIO_CODEC_LABEL); + sourceNote = getIntent().getStringExtra(MainActivity.EXTRA_SOURCE_NOTE); inputMime = getIntent().getStringExtra(MainActivity.EXTRA_INPUT_MIME); outputFormat = getIntent().getStringExtra(MainActivity.EXTRA_IMAGE_OUTPUT_FORMAT); @@ -200,6 +219,10 @@ public class ProcessingActivity extends Activity { if (videoBitrateLabel == null) videoBitrateLabel = videoBitrate > 0 ? formatVideoBitrate(videoBitrate) : "Auto"; if (audioMode == null) audioMode = "copy"; if (audioLabel == null) audioLabel = "Original / Copy"; + if (inputContainerLabel == null) inputContainerLabel = "Video"; + if (inputVideoCodecLabel == null) inputVideoCodecLabel = ""; + if (inputAudioCodecLabel == null) inputAudioCodecLabel = ""; + if (sourceNote == null) sourceNote = ""; if (inputMime == null) inputMime = ""; if (outputFormat == null) outputFormat = "jpeg"; @@ -220,25 +243,56 @@ public class ProcessingActivity extends Activity { return; } + String inputLine = buildInputVideoConfigText(); + if (isGpuEncoder(encoderName)) { txtConfig.setText( + inputLine + "Codec : " + codecLabel + "\n" + "Resolusi : " + resolutionLabel + "\n" + "Bitrate : " + videoBitrateLabel + "\n" + - "Audio : " + audioLabel + "Audio : " + audioLabel + + buildSourceNoteText() ); return; } txtConfig.setText( + inputLine + "Codec : " + codecLabel + "\n" + "Resolusi : " + resolutionLabel + "\n" + "CRF : " + crf + "\n" + "Preset : " + preset + "\n" + - "Audio : " + audioLabel + "Audio : " + audioLabel + + buildSourceNoteText() ); } + private String buildInputVideoConfigText() { + StringBuilder builder = new StringBuilder(); + + if (inputContainerLabel != null && inputContainerLabel.length() > 0) { + builder.append("Input : ").append(inputContainerLabel).append("\n"); + } + + if (inputVideoCodecLabel != null && inputVideoCodecLabel.length() > 0) { + builder.append("Video In : ").append(inputVideoCodecLabel).append("\n"); + } + + if (inputAudioCodecLabel != null && inputAudioCodecLabel.length() > 0) { + builder.append("Audio In : ").append(inputAudioCodecLabel).append("\n"); + } + + return builder.toString(); + } + + private String buildSourceNoteText() { + if (sourceNote == null || sourceNote.length() == 0) { + return ""; + } + return "\nAuto : " + sourceNote; + } + private void startCompression() { if (inputUri == null) { allowScreenOffAfterProcessing(); @@ -253,6 +307,7 @@ public class ProcessingActivity extends Activity { lastDisplayedProgress = 0; targetProgress = 0; smoothProgressRunning = false; + resetProcessingVisualState(); circleProgress.resetProgress(); txtElapsed.setText("Waktu berjalan: 00:00"); handler.post(elapsedRunnable); @@ -260,6 +315,7 @@ public class ProcessingActivity extends Activity { workerThread = new Thread(() -> { ParcelFileDescriptor inputPfd = null; ParcelFileDescriptor outputPfd = null; + File tempVideoFile = null; try { inputPfd = getContentResolver().openFileDescriptor(inputUri, "r"); @@ -280,6 +336,16 @@ public class ProcessingActivity extends Activity { final Uri finalOutputUri = outputUri; + // Video memakai temp file cache dulu agar -movflags +faststart aman. + // Jangan encode video langsung ke MediaStore FD, karena faststart bisa gagal + // saat av_write_trailer() pada custom AVIO/ContentResolver FD. + if (!imageJob) { + closeQuietly(outputPfd); + outputPfd = null; + + tempVideoFile = createVideoTempFile(outputName); + } + int result; if (imageJob) { result = NativeCompressor.compressImageFd( @@ -294,9 +360,9 @@ public class ProcessingActivity extends Activity { ) ); } else { - result = NativeCompressor.compressFd( + result = NativeCompressor.compressFdToPath( inputPfd.getFd(), - outputPfd.getFd(), + tempVideoFile.getAbsolutePath(), targetShortSide, inputRotationDegrees, crf, @@ -328,11 +394,16 @@ public class ProcessingActivity extends Activity { } if (result == 0) { - // Tutup output descriptor lebih dulu agar ukuran file final sudah flush - // sebelum dibaca untuk perbandingan original vs compressed. + // Tutup descriptor lebih dulu agar data sudah flush sebelum publish/copy. closeQuietly(outputPfd); outputPfd = null; + if (!imageJob) { + copyTempVideoToOutputUri(tempVideoFile, finalOutputUri); + deleteTempFile(tempVideoFile); + tempVideoFile = null; + } + publishOutput(finalOutputUri, outputMime, imageJob); final long compressedSizeBytes = getUriSize(finalOutputUri); @@ -346,10 +417,11 @@ public class ProcessingActivity extends Activity { handler.removeCallbacks(elapsedRunnable); handler.removeCallbacks(smoothProgressRunnable); allowScreenOffAfterProcessing(); - lastDisplayedProgress = 100; - circleProgress.setProgress(100); - txtStatus.setText("Selesai"); + showSuccessVisualState(); txtElapsed.setText("Total waktu: " + formatElapsed(endTimeMs - startTimeMs)); + if (layoutOutputCard != null) { + layoutOutputCard.setVisibility(View.VISIBLE); + } txtOutput.setText(outputResultText); btnShareVideo.setVisibility(View.VISIBLE); btnShareDoc.setVisibility(View.VISIBLE); @@ -386,14 +458,47 @@ public class ProcessingActivity extends Activity { } finally { closeQuietly(inputPfd); closeQuietly(outputPfd); + deleteTempFile(tempVideoFile); } }, imageJob ? "KCompressor-Image" : "KCompressor-Video"); workerThread.start(); } + private void resetProcessingVisualState() { + circleProgress.setVisibility(View.VISIBLE); + if (layoutOutputCard != null) { + layoutOutputCard.setVisibility(View.GONE); + } + txtOutput.setText(""); + + txtStatus.setTextColor(COLOR_STATUS_NORMAL); + txtStatus.setTextSize(STATUS_TEXT_SIZE_NORMAL_SP); + txtStatus.setTypeface(null, android.graphics.Typeface.NORMAL); + txtStatus.setText(imageJob ? "Menyiapkan gambar..." : "Menyiapkan video..."); + } + + private void showSuccessVisualState() { + lastDisplayedProgress = 100; + targetProgress = 100; + smoothProgressRunning = false; + + // Hilangkan circle progress dan angka persentase setelah sukses. + // Status akhir dibuat simple, besar, dan warnanya mengikuti warna progress circle. + circleProgress.setProgress(100); + circleProgress.setVisibility(View.GONE); + + txtStatus.setText("Selesai"); + txtStatus.setTextColor(COLOR_PROGRESS_SUCCESS); + txtStatus.setTextSize(STATUS_TEXT_SIZE_SUCCESS_SP); + txtStatus.setTypeface(null, android.graphics.Typeface.BOLD); + } + private void showFailed(int result) { finished = true; + if (layoutOutputCard != null) { + layoutOutputCard.setVisibility(View.GONE); + } handler.removeCallbacks(elapsedRunnable); handler.removeCallbacks(smoothProgressRunnable); allowScreenOffAfterProcessing(); @@ -583,6 +688,93 @@ public class ProcessingActivity extends Activity { } } + private File createVideoTempFile(String outputName) throws Exception { + File dir = new File(getCacheDir(), "video_transcode"); + if (!dir.exists() && !dir.mkdirs()) { + throw new IllegalStateException("Gagal membuat cache video: " + dir); + } + + String safeName = outputName == null ? "kcompressor_temp.mp4" : outputName; + safeName = safeName.replaceAll("[^a-zA-Z0-9._-]", "_"); + + File file = new File(dir, "tmp_" + System.currentTimeMillis() + "_" + safeName); + if (file.exists() && !file.delete()) { + throw new IllegalStateException("Gagal membersihkan temp lama: " + file); + } + + return file; + } + + private void copyTempVideoToOutputUri(File tempFile, Uri targetUri) throws Exception { + if (tempFile == null || !tempFile.exists() || tempFile.length() <= 0L) { + throw new IllegalStateException("Temp video kosong"); + } + + if (targetUri == null) { + throw new IllegalStateException("Output URI null"); + } + + FileInputStream input = null; + OutputStream output = null; + + try { + input = new FileInputStream(tempFile); + + if ("file".equals(targetUri.getScheme())) { + output = new java.io.FileOutputStream(new File(targetUri.getPath())); + } else { + output = getContentResolver().openOutputStream(targetUri, "w"); + } + + if (output == null) { + throw new IllegalStateException("Output stream null"); + } + + byte[] buffer = new byte[256 * 1024]; + while (true) { + if (cancelRequested) { + throw new IllegalStateException("Canceled"); + } + + int read = input.read(buffer); + if (read < 0) { + break; + } + + if (read > 0) { + output.write(buffer, 0, read); + } + } + + output.flush(); + } finally { + if (input != null) { + try { + input.close(); + } catch (Exception ignored) {} + } + + if (output != null) { + try { + output.close(); + } catch (Exception ignored) {} + } + } + } + + private void deleteTempFile(File file) { + if (file == null) { + return; + } + + try { + if (file.exists()) { + //noinspection ResultOfMethodCallIgnored + file.delete(); + } + } catch (Throwable ignored) {} + } + private String makeVideoOutputName(String encoderName, int targetShortSide, int crf, int videoBitrate) { String codec = (encoderName != null && (encoderName.contains("265") || encoderName.contains("hevc"))) ? "hevc" @@ -798,19 +990,24 @@ public class ProcessingActivity extends Activity { } private String buildOutputResultText(long originalSizeBytes, long compressedSizeBytes) { - String savedText = imageJob ? "Gambar disimpan di gallery" : "Video disimpan di gallery"; - - if (originalSizeBytes <= 0L || compressedSizeBytes <= 0L) { - return savedText + "\n\n" + - "Original : tidak diketahui\n" + - "Compressed : " + (compressedSizeBytes > 0L ? formatFileSize(compressedSizeBytes) : "tidak diketahui"); - } - - long delta = originalSizeBytes - compressedSizeBytes; - double finalRatioPercent = (compressedSizeBytes * 100.0) / originalSizeBytes; + String savedText = imageJob ? "Gambar disimpan di Gallery" : "Video disimpan di Gallery"; StringBuilder builder = new StringBuilder(); builder.append(savedText).append("\n\n"); + + if (originalSizeBytes <= 0L || compressedSizeBytes <= 0L) { + builder.append("Original : ") + .append(originalSizeBytes > 0L ? formatFileSize(originalSizeBytes) : "tidak diketahui") + .append("\n"); + builder.append("Compressed : ") + .append(compressedSizeBytes > 0L ? formatFileSize(compressedSizeBytes) : "tidak diketahui") + .append("\n"); + builder.append("Hemat : tidak diketahui"); + return builder.toString(); + } + + long delta = originalSizeBytes - compressedSizeBytes; + builder.append("Original : ").append(formatFileSize(originalSizeBytes)).append("\n"); builder.append("Compressed : ").append(formatFileSize(compressedSizeBytes)).append("\n"); @@ -820,20 +1017,14 @@ public class ProcessingActivity extends Activity { .append(formatFileSize(delta)) .append(" (") .append(formatPercent(savedPercent)) - .append("%)\n"); - builder.append("Ukuran akhir: ") - .append(formatPercent(finalRatioPercent)) - .append("% dari original"); + .append("%)"); } else { double largerPercent = ((-delta) * 100.0) / originalSizeBytes; - builder.append("Hasil : lebih besar ") + builder.append("Hemat : -") .append(formatFileSize(-delta)) - .append(" (+") + .append(" (lebih besar ") .append(formatPercent(largerPercent)) - .append("%)\n"); - builder.append("Ukuran akhir: ") - .append(formatPercent(finalRatioPercent)) - .append("% dari original"); + .append("%)"); } return builder.toString(); diff --git a/app/src/main/res/layout/activity_main_amoled.xml b/app/src/main/res/layout/activity_main_amoled.xml index 5d29d31..9f7641a 100644 --- a/app/src/main/res/layout/activity_main_amoled.xml +++ b/app/src/main/res/layout/activity_main_amoled.xml @@ -25,7 +25,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="Native FFmpeg video compressor" + android:text="All in one media compressor" android:textColor="#9CA3AF" android:textSize="14sp" /> @@ -97,13 +97,31 @@ android:textSize="16sp" android:textStyle="bold" /> - + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + - + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + - + + @@ -76,16 +84,36 @@ - + android:layout_marginTop="16dp" + android:background="@drawable/bg_amoled_card" + android:orientation="vertical" + android:padding="16dp" + android:visibility="gone"> + + + + + + + +