From ad547a6b5986815fda458221149728d9d9ab1d87 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 25 Feb 2021 19:22:25 +0000 Subject: restore Build,TODO from r57911 git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/libs/pplib/pplib-src/.gitattributes | 10 + Build/source/libs/pplib/pplib-src/.gitignore | 8 + Build/source/libs/pplib/pplib-src/.gitmodules | 3 + Build/source/libs/pplib/pplib-src/.travis.yml | 20 + Build/source/libs/pplib/pplib-src/CMakeLists.txt | 6 + Build/source/libs/pplib/pplib-src/README.md | 9 + .../libs/pplib/pplib-src/azure-pipelines.yml | 36 + Build/source/libs/pplib/pplib-src/doc/Makefile | 20 + .../doc/_build/doctrees/environment.pickle | Bin 0 -> 32928 bytes .../doc/_build/doctrees/ppapi-1.x.doctree | Bin 0 -> 167607 bytes .../doc/_build/doctrees/ppapi-2.x.doctree | Bin 0 -> 167117 bytes .../pplib-src/doc/_build/doctrees/ppapi.doctree | Bin 0 -> 165058 bytes .../pplib-src/doc/_build/doctrees/ppcode.doctree | Bin 0 -> 64496 bytes .../pplib-src/doc/_build/doctrees/pplib.doctree | Bin 0 -> 3371 bytes .../pplib-src/doc/_build/doctrees/ppnew.doctree | Bin 0 -> 25753 bytes .../pplib/pplib-src/doc/_build/html/.buildinfo | 4 + .../doc/_build/html/_sources/ppapi-1.x.rst.txt | 937 ++ .../doc/_build/html/_sources/ppapi-2.x.rst.txt | 937 ++ .../doc/_build/html/_sources/ppapi.rst.txt | 937 ++ .../doc/_build/html/_sources/ppcode.rst.txt | 101 + .../doc/_build/html/_sources/pplib.rst.txt | 15 + .../doc/_build/html/_sources/ppnew.rst.txt | 103 + .../doc/_build/html/_static/ajax-loader.gif | Bin 0 -> 673 bytes .../doc/_build/html/_static/background_b01.png | Bin 0 -> 78 bytes .../pplib-src/doc/_build/html/_static/basic.css | 676 ++ .../pplib-src/doc/_build/html/_static/bizstyle.css | 490 + .../pplib-src/doc/_build/html/_static/bizstyle.js | 41 + .../doc/_build/html/_static/comment-bright.png | Bin 0 -> 756 bytes .../doc/_build/html/_static/comment-close.png | Bin 0 -> 829 bytes .../pplib-src/doc/_build/html/_static/comment.png | Bin 0 -> 641 bytes .../doc/_build/html/_static/css3-mediaqueries.js | 1 + .../_build/html/_static/css3-mediaqueries_src.js | 1104 ++ .../pplib-src/doc/_build/html/_static/doctools.js | 315 + .../_build/html/_static/documentation_options.js | 10 + .../doc/_build/html/_static/down-pressed.png | Bin 0 -> 222 bytes .../pplib-src/doc/_build/html/_static/down.png | Bin 0 -> 202 bytes .../pplib-src/doc/_build/html/_static/file.png | Bin 0 -> 286 bytes .../doc/_build/html/_static/jquery-3.2.1.js | 10253 +++++++++++++++++++ .../pplib-src/doc/_build/html/_static/jquery.js | 4 + .../doc/_build/html/_static/language_data.js | 297 + .../pplib-src/doc/_build/html/_static/minus.png | Bin 0 -> 90 bytes .../pplib-src/doc/_build/html/_static/plus.png | Bin 0 -> 90 bytes .../pplib-src/doc/_build/html/_static/pygments.css | 69 + .../doc/_build/html/_static/searchtools.js | 481 + .../doc/_build/html/_static/underscore-1.3.1.js | 999 ++ .../doc/_build/html/_static/underscore.js | 31 + .../doc/_build/html/_static/up-pressed.png | Bin 0 -> 214 bytes .../pplib/pplib-src/doc/_build/html/_static/up.png | Bin 0 -> 203 bytes .../doc/_build/html/_static/websupport.js | 808 ++ .../pplib/pplib-src/doc/_build/html/genindex.html | 85 + .../pplib/pplib-src/doc/_build/html/objects.inv | 6 + .../pplib/pplib-src/doc/_build/html/ppapi-1.x.html | 1030 ++ .../pplib/pplib-src/doc/_build/html/ppapi-2.x.html | 1031 ++ .../pplib/pplib-src/doc/_build/html/ppapi.html | 1030 ++ .../pplib/pplib-src/doc/_build/html/ppcode.html | 996 ++ .../pplib/pplib-src/doc/_build/html/pplib.html | 176 + .../pplib/pplib-src/doc/_build/html/ppnew.html | 209 + .../pplib/pplib-src/doc/_build/html/search.html | 97 + .../pplib/pplib-src/doc/_build/html/searchindex.js | 1 + Build/source/libs/pplib/pplib-src/doc/conf.py | 156 + Build/source/libs/pplib/pplib-src/doc/make.bat | 36 + .../source/libs/pplib/pplib-src/doc/ppapi-1.x.rst | 937 ++ .../source/libs/pplib/pplib-src/doc/ppapi-2.x.rst | 937 ++ Build/source/libs/pplib/pplib-src/doc/ppcode.rst | 101 + Build/source/libs/pplib/pplib-src/doc/pplib.rst | 15 + Build/source/libs/pplib/pplib-src/doc/ppnew.rst | 103 + .../source/libs/pplib/pplib-src/src/CMakeLists.txt | 151 + Build/source/libs/pplib/pplib-src/src/Makefile | 99 + Build/source/libs/pplib/pplib-src/src/Makefile.vc | 98 + Build/source/libs/pplib/pplib-src/src/ppapi.h | 404 + Build/source/libs/pplib/pplib-src/src/pparray.c | 145 + Build/source/libs/pplib/pplib-src/src/pparray.h | 7 + Build/source/libs/pplib/pplib-src/src/ppconf.h | 76 + Build/source/libs/pplib/pplib-src/src/ppcrypt.c | 525 + Build/source/libs/pplib/pplib-src/src/ppcrypt.h | 67 + Build/source/libs/pplib/pplib-src/src/ppdict.c | 166 + Build/source/libs/pplib/pplib-src/src/ppdict.h | 7 + Build/source/libs/pplib/pplib-src/src/ppfilter.h | 10 + Build/source/libs/pplib/pplib-src/src/ppheap.c | 40 + Build/source/libs/pplib/pplib-src/src/ppheap.h | 46 + Build/source/libs/pplib/pplib-src/src/pplib.h | 22 + Build/source/libs/pplib/pplib-src/src/ppload.c | 2769 +++++ Build/source/libs/pplib/pplib-src/src/ppload.h | 58 + Build/source/libs/pplib/pplib-src/src/ppstream.c | 491 + Build/source/libs/pplib/pplib-src/src/ppstream.h | 10 + Build/source/libs/pplib/pplib-src/src/pptest1.c | 104 + Build/source/libs/pplib/pplib-src/src/pptest2.c | 138 + Build/source/libs/pplib/pplib-src/src/pptest3.c | 123 + Build/source/libs/pplib/pplib-src/src/ppxref.c | 215 + Build/source/libs/pplib/pplib-src/src/ppxref.h | 35 + .../source/libs/pplib/pplib-src/src/util/README.md | 8 + .../libs/pplib/pplib-src/src/util/utilbasexx.c | 1742 ++++ .../libs/pplib/pplib-src/src/util/utilbasexx.h | 111 + .../libs/pplib/pplib-src/src/util/utilcrypt.c | 1190 +++ .../libs/pplib/pplib-src/src/util/utilcrypt.h | 90 + .../libs/pplib/pplib-src/src/util/utilcryptdef.h | 32 + .../libs/pplib/pplib-src/src/util/utildecl.h | 28 + .../libs/pplib/pplib-src/src/util/utilflate.c | 322 + .../libs/pplib/pplib-src/src/util/utilflate.h | 21 + .../libs/pplib/pplib-src/src/util/utilfpred.c | 778 ++ .../libs/pplib/pplib-src/src/util/utilfpred.h | 23 + .../source/libs/pplib/pplib-src/src/util/utiliof.c | 2993 ++++++ .../source/libs/pplib/pplib-src/src/util/utiliof.h | 673 ++ .../source/libs/pplib/pplib-src/src/util/utillog.c | 60 + .../source/libs/pplib/pplib-src/src/util/utillog.h | 10 + .../source/libs/pplib/pplib-src/src/util/utillzw.c | 705 ++ .../source/libs/pplib/pplib-src/src/util/utillzw.h | 30 + .../source/libs/pplib/pplib-src/src/util/utilmd5.c | 447 + .../source/libs/pplib/pplib-src/src/util/utilmd5.h | 49 + .../source/libs/pplib/pplib-src/src/util/utilmem.c | 67 + .../source/libs/pplib/pplib-src/src/util/utilmem.h | 16 + .../libs/pplib/pplib-src/src/util/utilmemallc.h | 569 + .../libs/pplib/pplib-src/src/util/utilmemallh.h | 36 + .../libs/pplib/pplib-src/src/util/utilmemheap.c | 1078 ++ .../libs/pplib/pplib-src/src/util/utilmemheap.h | 188 + .../libs/pplib/pplib-src/src/util/utilmemheapiof.c | 142 + .../libs/pplib/pplib-src/src/util/utilmemheapiof.h | 43 + .../libs/pplib/pplib-src/src/util/utilmeminfo.c | 38 + .../libs/pplib/pplib-src/src/util/utilmeminfo.h | 9 + .../libs/pplib/pplib-src/src/util/utilnumber.c | 1177 +++ .../libs/pplib/pplib-src/src/util/utilnumber.h | 428 + .../libs/pplib/pplib-src/src/util/utilplat.h | 31 + .../source/libs/pplib/pplib-src/src/util/utilsha.c | 1065 ++ .../source/libs/pplib/pplib-src/src/util/utilsha.h | 79 + .../source/libs/pplib/pplib-src/test/luaimage.pdf | Bin 0 -> 169842 bytes .../libs/pplib/pplib-src/test/luaimage.pdf.out | 36 + Build/source/libs/pplib/pplib-src/test/out1 | 11 + Build/source/libs/pplib/pplib-src/test/out2 | 1 + Build/source/libs/pplib/pplib-src/test/out3 | 67 + 129 files changed, 45870 insertions(+) create mode 100644 Build/source/libs/pplib/pplib-src/.gitattributes create mode 100644 Build/source/libs/pplib/pplib-src/.gitignore create mode 100644 Build/source/libs/pplib/pplib-src/.gitmodules create mode 100644 Build/source/libs/pplib/pplib-src/.travis.yml create mode 100644 Build/source/libs/pplib/pplib-src/CMakeLists.txt create mode 100644 Build/source/libs/pplib/pplib-src/README.md create mode 100644 Build/source/libs/pplib/pplib-src/azure-pipelines.yml create mode 100644 Build/source/libs/pplib/pplib-src/doc/Makefile create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi.doctree create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/.buildinfo create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-1.x.rst.txt create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi.rst.txt create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/pplib.rst.txt create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppnew.rst.txt create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/ajax-loader.gif create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/background_b01.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/basic.css create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.css create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-bright.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-close.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries_src.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/doctools.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/documentation_options.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/down-pressed.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/down.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/file.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/jquery-3.2.1.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/jquery.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/language_data.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/minus.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/plus.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/pygments.css create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/searchtools.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/underscore-1.3.1.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/underscore.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/up-pressed.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/up.png create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/_static/websupport.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/genindex.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/objects.inv create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/ppcode.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/pplib.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/ppnew.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/search.html create mode 100644 Build/source/libs/pplib/pplib-src/doc/_build/html/searchindex.js create mode 100644 Build/source/libs/pplib/pplib-src/doc/conf.py create mode 100644 Build/source/libs/pplib/pplib-src/doc/make.bat create mode 100644 Build/source/libs/pplib/pplib-src/doc/ppapi-1.x.rst create mode 100644 Build/source/libs/pplib/pplib-src/doc/ppapi-2.x.rst create mode 100644 Build/source/libs/pplib/pplib-src/doc/ppcode.rst create mode 100644 Build/source/libs/pplib/pplib-src/doc/pplib.rst create mode 100644 Build/source/libs/pplib/pplib-src/doc/ppnew.rst create mode 100644 Build/source/libs/pplib/pplib-src/src/CMakeLists.txt create mode 100644 Build/source/libs/pplib/pplib-src/src/Makefile create mode 100644 Build/source/libs/pplib/pplib-src/src/Makefile.vc create mode 100644 Build/source/libs/pplib/pplib-src/src/ppapi.h create mode 100644 Build/source/libs/pplib/pplib-src/src/pparray.c create mode 100644 Build/source/libs/pplib/pplib-src/src/pparray.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppconf.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppcrypt.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppcrypt.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppdict.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppdict.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppfilter.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppheap.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppheap.h create mode 100644 Build/source/libs/pplib/pplib-src/src/pplib.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppload.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppload.h create mode 100644 Build/source/libs/pplib/pplib-src/src/ppstream.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppstream.h create mode 100644 Build/source/libs/pplib/pplib-src/src/pptest1.c create mode 100644 Build/source/libs/pplib/pplib-src/src/pptest2.c create mode 100644 Build/source/libs/pplib/pplib-src/src/pptest3.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppxref.c create mode 100644 Build/source/libs/pplib/pplib-src/src/ppxref.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/README.md create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilbasexx.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilbasexx.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilcrypt.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilcrypt.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilcryptdef.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utildecl.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilflate.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilflate.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilfpred.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilfpred.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utiliof.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utiliof.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utillog.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utillog.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utillzw.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utillzw.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmd5.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmd5.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmem.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmem.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmemallc.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmemallh.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmemheap.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmemheapiof.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmemheapiof.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmeminfo.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilmeminfo.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilnumber.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilnumber.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilplat.h create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilsha.c create mode 100644 Build/source/libs/pplib/pplib-src/src/util/utilsha.h create mode 100644 Build/source/libs/pplib/pplib-src/test/luaimage.pdf create mode 100644 Build/source/libs/pplib/pplib-src/test/luaimage.pdf.out create mode 100644 Build/source/libs/pplib/pplib-src/test/out1 create mode 100644 Build/source/libs/pplib/pplib-src/test/out2 create mode 100644 Build/source/libs/pplib/pplib-src/test/out3 (limited to 'Build/source/libs/pplib/pplib-src') diff --git a/Build/source/libs/pplib/pplib-src/.gitattributes b/Build/source/libs/pplib/pplib-src/.gitattributes new file mode 100644 index 00000000000..8d68adf9ae9 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/.gitattributes @@ -0,0 +1,10 @@ +*.c text=auto eol=lf +*.h text=auto eol=lf +Makefile text=auto eol=lf + +*.rst binary +*.png binary +*.jpg binary +*.css binary +*.html binary +*.js binary \ No newline at end of file diff --git a/Build/source/libs/pplib/pplib-src/.gitignore b/Build/source/libs/pplib/pplib-src/.gitignore new file mode 100644 index 00000000000..84d76071422 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/.gitignore @@ -0,0 +1,8 @@ +src/build/* +src/CMakeFiles/* +src/CMakeCache.txt +src/.vs/* +src/.cproject +src/.project +src/.settings +zlib/* \ No newline at end of file diff --git a/Build/source/libs/pplib/pplib-src/.gitmodules b/Build/source/libs/pplib/pplib-src/.gitmodules new file mode 100644 index 00000000000..4792336ecfc --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/.gitmodules @@ -0,0 +1,3 @@ +[submodule "zlib"] + path = zlib + url = git://github.com/madler/zlib.git diff --git a/Build/source/libs/pplib/pplib-src/.travis.yml b/Build/source/libs/pplib/pplib-src/.travis.yml new file mode 100644 index 00000000000..2f1c9a01cbc --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/.travis.yml @@ -0,0 +1,20 @@ +language: c + +script: + - mkdir build + - cd build + - cmake .. + - make -j 2 + - make -j 2 test + +matrix: + include: + - os: linux + compiler: clang + - os: linux + compiler: gcc + - os: osx + osx_image: xcode10.2 + allow_failures: + - os: osx + osx_image: xcode8 diff --git a/Build/source/libs/pplib/pplib-src/CMakeLists.txt b/Build/source/libs/pplib/pplib-src/CMakeLists.txt new file mode 100644 index 00000000000..8c2ea1e89ae --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) + +add_subdirectory(zlib) +add_subdirectory(src) + +enable_testing() diff --git a/Build/source/libs/pplib/pplib-src/README.md b/Build/source/libs/pplib/pplib-src/README.md new file mode 100644 index 00000000000..c684e9ed7ce --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/README.md @@ -0,0 +1,9 @@ +## pplib - pdf disassembling library for LuaTeX + +This is `plib` - PDF disassembling library for LuaTeX (http://luatex.org) + +The library has no LuaTeX dependency, it depends only on `zlib`. +However, `pplib` was tailor-made for LuaTeX and its functionals are +somewhat limited (eg. read-only PDF support). + +Author: Paweł Jackowski p.jackowski@gust.org.pl diff --git a/Build/source/libs/pplib/pplib-src/azure-pipelines.yml b/Build/source/libs/pplib/pplib-src/azure-pipelines.yml new file mode 100644 index 00000000000..365abe00716 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/azure-pipelines.yml @@ -0,0 +1,36 @@ +# C/C++ with GCC +# Build your C/C++ project with GCC using make. +# Add steps that publish test results, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/c-cpp/gcc + +trigger: +- master + +jobs: + +- job: Build + + strategy: + matrix: + linux: + imageName: "ubuntu-16.04" + mac: + imageName: "macos-10.13" + windows: + imageName: "vs2017-win2016" + maxParallel: 3 + + pool: + vmImage: $(imageName) + + steps: + - checkout: self + submodules: recursive + - task: CMake@1 + displayName: 'CMake ..' + inputs: + cmakeArgs: '..' + - task: CMake@1 + displayName: 'CMake --build . --config Debug' + inputs: + cmakeArgs: '--build . --config Debug' diff --git a/Build/source/libs/pplib/pplib-src/doc/Makefile b/Build/source/libs/pplib/pplib-src/doc/Makefile new file mode 100644 index 00000000000..3ca7eeebf89 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = pplib +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle new file mode 100644 index 00000000000..c4d657a1115 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree new file mode 100644 index 00000000000..bd22032c659 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree new file mode 100644 index 00000000000..d8c91b48bed Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi.doctree new file mode 100644 index 00000000000..9e432d80125 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi.doctree differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree new file mode 100644 index 00000000000..a33b506208e Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree new file mode 100644 index 00000000000..0d5e84fe5a5 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree new file mode 100644 index 00000000000..5c152d321a5 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/.buildinfo b/Build/source/libs/pplib/pplib-src/doc/_build/html/.buildinfo new file mode 100644 index 00000000000..ec014001dee --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 5a0a9f8c8bb0798c3d499fe9e55f5963 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-1.x.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-1.x.rst.txt new file mode 100644 index 00000000000..df661a7b82d --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-1.x.rst.txt @@ -0,0 +1,937 @@ + +``pplib`` 1.x +============= + +``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C. + +C-API +===== + +Types +----- + +``pplib`` defines several C-types to represent PDF types: + +- ``ppint`` - signed integer (``int64_t``) +- ``ppnum`` - real number (double) +- ``ppname`` - PDF name +- ``ppstring`` - PDF string +- ``pparray`` - PDF array +- ``ppdict`` - PDF dict +- ``ppstream`` - PDF stream +- ``ppref`` - PDF indirect reference +- ``ppobj`` - a container of all above + +Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``). + +Other API types: + +- ``ppdoc`` - PDF document +- ``ppxref`` - cross-references table +- ``ppcontext`` - ... later +- ``pprect`` - rectangle +- ``ppmatrix`` - matrix + +Integer, number, name and string are treated as simple types. +Names and strings are actually C-structures, but exposed to API as typedefs to ``const char *``. +Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures, +and you operate it their pointers. So when you declare a simple type variable you say:: + + ppuint u; + ppnum n; + ppname name; + ppstring string; + ... + +And when you declare a compound type you operate on pointers:: + + ppobj *obj; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + ppdoc *pdf; + +Some of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete +(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in +the header. [At some points it's not clear to me what to hide and what to expose, will see.] The library itself +uses ``pplib.h`` but for auxilary applications including a standalone ``ppapi.h`` header should be enough. + +``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed, +so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because +then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library +internals to unconst. Besides, nothing is really const for C type casts. + +Object +------ + +A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier +(integer) and union of values:: + + struct ppobj { + ppobjtp type; + union { + ppint integer; + ppnum number; + ppname name; + ppstring string; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + void *any; + }; + }; + +Object type is one of constants (enum):: + + PPNONE + PPNULL + PPBOOL + PPINT + PPNUM + PPNAME + PPSTRING + PPARRAY + PPDICT + PPSTREAM + PPREF + +The type determines the structure member you're allowed to access:: + + ppobj *obj; + ... + switch (obj->type) + { + case PPNONE: // shouldn't actually happen, indicates some failure + break; + case PPNULL: // valid PDF null object, no value + break; + case PPBOOL: // do something with obj->integer (ppint), value 0 or 1 + break; + case PPINT: // do something with obj->integer (ppint) + break; + case PPNUM: // do something with obj->number (ppnum) + break; + case PPNAME: // do something with obj->name (ppname) + break; + case PPSTRING: // do something with obj->string (ppstring) + break; + case PPARRAY: // do something with obj->array (pparray *) + break; + case PPDICT: // do something with obj->dict (ppdict *) + break; + case PPSTREAM: // do something with obj->stream (ppstream *) + break; + case PPREF: // do something with obj->ref (ppref *) + break; + } + +More often then not you know exactly what type of object value is expected, in which case +you may use one of the following macros:: + + // returns 1 if o->type is PPNULL + int ppobj_get_null(o) \ + + // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise + int ppobj_get_bool(o, v) + + // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise + int ppobj_get_int(o, v) + + // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise + int ppobj_get_uint(o, v) + + // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise + int ppobj_get_num(o, v) + + // if o->type is PPNAME returns the name, NULL otherwise + ppname ppobj_get_name(o) + + // if o->type is PPSTRING returns the string, NULL otherwise + ppstring ppobj_get_string(o) + + // if o->type is PPARRAY returns the array, NULL otherwise + pparray * ppobj_get_array(o) + + // if o->type is PPDICT returns the dict, NULL otherwise + ppdict * ppobj_get_dict(o) + + // if o->type is PPSTREAM returns the stream, NULL otherwise + ppstream * ppobj_get_stream(o) + + // if o->type is PPREF returns the reference, NULL otherwise + ppref * ppobj_get_ref(o) + +Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number, +you should also handle integer (eg. '1' used instead of '1.0'). + +It is a common case that the object is given as an indirect reference, but what you actually +want is not the reference, but the object referred by it. Here is a helper for it:: + + // if o->type is PPREF, returns what the reference points, otherwise returns o + ppobj * ppobj_rget_obj(o) + +Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check +for the expected type, but if the object is PPREF, it jumps to the target object. +So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT +or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT. + +Names +----- + +PDF names are represented as ``ppname``. +I find it convenient to have ``ppname`` type pretending ``const char *``. This allows to use ``ppname`` +in all C-style string functions like ``printf("%s", name)``. + +Be aware, however, that ``ppname`` is actually a C-structure. It is perfectly ok to cast ``ppname`` to ``const char *``:: + + ppname name; + ... + (const char *)name; + +But reverse is forbidden:: + + const char *cstr = "cstring"; + ... + (ppname)cstr; // expect segmentation fault soon + +For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use +``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``:: + + size_t ppname_size(ppname name); // macro, returns length of name in bytes + +In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``. +Use macros:: + + int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string + int ppname_eq(ppname name, ppname other); // to compare ppname with a different name + +If you'll use ``pplib`` to parse contents streams, you may need to distinguish names from operators +(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both +cases PDF parser will produce ``ppname`` but can be distingushed with:: + + int ppname_exec(ppname name); // returns non-zero if name is executable + +Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form). +Leading '/' is omitted, though. One may need a decoded name, with no PDF escapes. +A pair of functions provides a simple interface to switch between those two forms:: + + ppname ppname_decoded (ppname name); // returns decoded (unescaped) form of the name + ppname ppname_encoded (ppname name); // returns encoded (escaped) form of the name + +In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical. +In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form +and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego +in whatever direction needs no extra decoding or allocation costs. + +String +------ + +PDF strings have the same internal construction as names, so most of names description above applies to strings as well. +``ppstring`` is a typedef of ``const char *``, roughly ``'\0'`` terminiated C-string. To get the size of the string:: + + size_t ppstring_size(ppstring string); // macro, returns the length of the string in bytes + +Strings are provided in their raw form, preserving PDF specific escapes, but with no +``()`` or ``<>`` delims. To distinguish plain strings from hex strings:: + + int ppstring_hex(ppstring string); // macro, returns non zero if hex string + +Or if you prefer:: + + switch (ppstring_type(string)) + { + case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF + break; + case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF + break; + case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF + break; + } + +The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams... +No matter how the string is given in PDF (plain or hex), here are two functions to +switch between encoded and decoded strings forms:: + + ppstring ppstring_decoded (ppstring string); // returns decoded string possibly with PDF escapes + ppstring ppstring_encoded (ppstring string); // returns encoded string with no PDF escapes + +For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding). +Plain strings usually contains printable ASCII characters, but they might contain any binary data. +As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one. +Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego. + +No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string +is considered unicode. ``ppstring`` object *knows* it is unicode or not:: + + switch (ppstring_utf(string)) + { + case PPSTRING_UTF16LE: // unicode string, utf16le + break; + case PPSTRING_UTF16BE: // unicode string, utf16be + break; + default: // no unicode + } + +Or simply:: + + if (ppstring_utf(string) != 0) { + // handle unicode string + } + +If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it. +Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()`` +always returns the size in bytes. + +Array +----- + +PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures. +To get the size:: + + size_t pparray_size(pparray *array) // macro, returns the number of array items + +To get ``ppobj *`` at a given index:: + + ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check) + ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check) + ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get() + +Iterating over array elements:: + + pparray *array; + size_t index, size; + ppobj *obj; + for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj)) + { + // do something with index and obj + } + +There is no magic first/next macros, just iteration over pointers. One could also use something like:: + + for (index = 0, size = array->size; index < size; ++index) + { + obj = pparray_at(array, index); + // do something with index and obj + } + +When getting values from array and expecting a result of known type, use one of the following:: + + int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value + int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value + int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value + int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value + ppname pparray_get_name (pparray *array, size_t index); // get ppname value + ppstring pparray_get_string (pparray *array, size_t index); // get ppstring value + pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value + ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value + ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value + +As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches. +Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL. + +Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart that +that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that +there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect. +To get the stream from array use:: + + ppstream * pparray_rget_stream (pparray *array, size_t index); + +Dict +---- + +PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel +C-array of ``ppname`` pointers. To get the size of a dict:: + + size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs + +To get the value at a given index (integer):: + + ppobj * ppdict_at(ppdict *dict, index) // macro, no index check + +To get the name (key) at a given index:: + + ppname ppdict_key(ppdict *dict, index) // macro, no index check + +To iterate over dict key-val pairs:: + + ppdict *dict; + ppname *pkey; + ppobj *obj; + + for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) + { + // do something with *pkey and obj + } + +There is no magic in first/next macros, just iteration through keys and values lists pointers. +For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL`` +is used as the loop condition. One may also iterate via indices:: + + ppdict *dict; + size_t index, size; + ppname key; + ppobj *obj; + for (index = 0, size = ppdict_size(dict); index < size; ++index) + { + key = ppdict_key(dict, index); + obj = ppdict_at(dict, index); + // do something with key and obj + } + +To get the object associated with a given name, use one of the following:: + + ppobj * ppdict_get_obj (ppdict *dict, const char *name); + int ppdict_get_bool (ppdict *dict, const char *name, int *v); + int ppdict_get_int (ppdict *dict, const char *name, ppint *v); + int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v); + int ppdict_get_num (ppdict *dict, const char *name, ppnum *v); + ppname ppdict_get_name (ppdict *dict, const char *name); + ppstring ppdict_get_string (ppdict *dict, const char *name); + pparray * ppdict_get_array (ppdict *dict, const char *name); + ppdict * ppdict_get_dict (ppdict *dict, const char *name); + ppref * ppdict_get_ref (ppdict *dict, const char *name); + +Note that all getters accepts ``const char *`` as key, so it is ok to say:: + + ppdict_rget_dict(dict, "Resources"); + +as well as:: + + ppdic_rget_dict(dict, name); // ppname name + +Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences +indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function, +but there is:: + + ppstream * ppdict_rget_stream (ppdict *dict, const char *name); + +So far dicts comes with no names mapping, so by-name dict accessors perform a linear search +through the keys list. PDF dicts are usually small, so it is fast enough. +Building names lookup for every dict in PDF makes no sense I think, as ``pplib`` applications +will query just several dicts I guess.. However, some apps may extensively query +resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts +is still considered. + +Stream +------ + +PDF streams are represented as ``ppstream`` objects. To get the stream dict:: + + ppdict * ppstream_dict(ppstream *stream) // macro + +To read the stream data:: + + uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode); + uint8_t * ppstream_next (ppstream *stream, size_t *size); + void ppstream_done (ppstream *stream); + +Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk. +``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()`` +must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``, +no matter if the stream has been read to the end or not. The stream data iterator in use:: + + uint8_t *data; + size_t size; + ppstream *stream; + int decode = 1; // 1 - get decompressed, 0 - get raw + + for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size)) + { + // do something with data and its size + } + ppstream_done(stream); + +Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk +of data just after you ot that. So the following is wrong:: + + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_next(stream, &size); + data3 = ppstream_next(stream, &size); + some_output(data1, size); + some_output(data2, size); + +The reader calls usually return the same pointer to internal buffer, just filled with a different data. +``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader. + +If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result. +You can check if the stream is actually compressed with:: + + ppstream_compressed(stream) // macro, returns non zero if /Filter is present + +It might be necessary to load the entire stream data at once:: + + uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode); + +If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call +``ppstream_done(stream)`` after using returned data. + +``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader. +The stream itself remains a valid object (eg. one can read it again if necessary), +but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream, +but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read. + +Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong:: + + data1 = ppstream_all(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_first(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + +To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``). +But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the +final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should +give the same results:: + + ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there + ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same + +A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``, +the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers. +``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats +some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects. +If you suffer from this, you can optionally use a pair of functions:: + + void ppstream_init_buffers (void); + void ppstream_free_buffers (void); + +The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader, +so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once +as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer. + +Filters +------- + +In version v1.00 (20190916) ``ppstream`` API has been extended with filters information. +``ppstream`` knows its filter(s) and keps it as ``stream->filter``:: + + // ppstream *stream; + ppstream_filter *info = &stream->filter; + +``ppstream_filter`` is the following structure:: + + typedef struct { + ppstreamtp *filters; // c-array of filter identifiers (enum integers) + ppdict **params; // c-array of ppdict pointers + size_t count; // number of filters, length of the arrays (typically 1) + } ppstream_filter; + +If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants:: + + PPSTREAM_BASE16 /* /ASCIIHexDecode */ + PPSTREAM_BASE85 /* /ASCII85Decode */ + PPSTREAM_RUNLENGTH /* /RunLengthDecode */ + PPSTREAM_FLATE /* /FlateDecode */ + PPSTREAM_LZW /* /LZWDecode */ + PPSTREAM_CCITT /* /CCITTFaxDecode */ + PPSTREAM_DCT /* /DCTDecode */ + PPSTREAM_JBIG2 /* /JBIG2Decode */ + PPSTREAM_JPX /* /JPXDecode */ + PPSTREAM_CRYPT /* /Crypt */ + +Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL +if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there, +for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``). + +``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers +(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers:: + + void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode); + +The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows +how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF). + +To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name:: + + const char * ppstream_filter_name[]; + +To covert ``ppname`` to filter identifier:: + + int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype); + // returns 1 and sets filtertype if filtername is the proper filter name + +Additional information about the stream can be fetched from macros:: + + ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */ + ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */ + ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */ + +``stream->flags`` is a binary sum of the following:: + + PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */ + PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */ + PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */ + PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */ + +Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead. +And there is some more, see ``ppapi.h``. + +Ref +--- + +Indirect objects are represented as ``ppref`` structure. To get the object that the +reference refers to:: + + ppobj * ppref_obj(ppref *ref) // macro + +``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs +to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references +on-fly. So if there is a dict with indirect objects:: + + << + /Type /Page + /Resources 123 0 R + ... + >> + +the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value. +If you need more, access ``ppref`` members:: + + struct ppref { + ppobj object; // target object + ppuint number, version; // identifiers + size_t offset; // file offset (useless for you, may be zero for compressed objects) + ppuint length; // the length of the original object data + ppxref *xref; // cross reference table it belongs to + }; + + +XRef +---- + +Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer). +To get top document xref:: + + ppxref * ppdoc_xref (ppdoc *pdf); + +To get previous (older) xref:: + + ppxref * ppxref_prev (ppxref *xref); + +To find an object of a given refnumber:: + + ppref * ppxref_find (ppxref *xref, ppuint refnumber); + +[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns +the newest available version of a given object rather than the object in a given body.] + +PDF +--- + +PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer). +To load a document from file:: + + ppdoc * ppdoc_load (const char *filename); + +To load a document from memory data:: + + ppdoc * ppdoc_mem (const void *data, size_t size); + +The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``. + +Both loaders returns ``NULL`` on failure. + +To free ``ppdoc`` and all objects it refers to:: + + void ppdoc_free (ppdoc *pdf); + +So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions +for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all +beings it refers to. It also means that every object described so far is alive as long as the containing +``ppdoc`` is alive. + +To access main PDF dicts:: + + ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict + ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer + ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer + +To get the PDF version:: + + const char * ppdoc_version_string (ppdoc *pdf); // version string + int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers + +To get the file size of the source PDF document:: + + size_t ppdoc_file_size (ppdoc *pdf); + +To get the number of objects in all xrefs:: + + ppuint ppdoc_objects (ppdoc *pdf); + +To get the approx usage of memory:: + + size_t ppdoc_memory (ppdoc *pdf, size_t *waste); + +Encryption +---------- + +``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered. +In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output. +It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting +for a password), but some features (eg. printing) may restricted by the application. + +When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing +an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives +a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries +set to ``null``. + +After loading a document you should check encryption status with:: + + ppcrypt_status ppdoc_crypt_status (ppdoc *pdf); + +``ppcrypt_status`` (integer) may have the following values: + + ``PPCRYPT_NONE`` - no encryption, go ahead + ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead + ``PPCRYPT_PASS`` - encryption present, need non-empty password + ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec) + +If a password is needed, you can provide one with:: + + ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength, + const void *ownerpass, size_t ownerpasslength); + +Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough +to know that having one of them is enough to decrypt the document. If you know the password, you probably mean +``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password +succeeds and the previous status otherwise. Your custom loader function may look like that:: + + ppdoc *pdf; + pdf = ppdoc_load("file.pdf"); + if (pdf == NULL) + return NULL; + switch (ppdoc_crypt_status(pdf)) + { + case PPCRYPT_NONE: + case PPCRYPT_DONE: + return pdf; + case PPCRYPT_PASS: + if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || + ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE) + return pdf; + printf("sorry, password needed\n"); + ppdoc_free(pdf); + return NULL; + case PPCRYPT_FAIL: + printf("sorry, encryption failed\n"); + ppdoc_free(pdf); + return NULL; + } + +[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.] + +If you'd like to know what permissions are given/restricted to encrypted document:: + + ppint ppdoc_permissions (ppdoc *pdf); + +Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab):: + + PPDOC_ALLOW_PRINT // printing + PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages + PPDOC_ALLOW_COPY // copying, copying for accessibility + PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing + PPDOC_ALLOW_EXTRACT // contents copying for accessibility + PPDOC_ALLOW_ASSEMBLY // (no effect) + PPDOC_ALLOW_PRINT_HIRES // (no effect) + +``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings +and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered). +Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted. +So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption. + +In encrypted documents most of streams are encrypted. To check if a given stream is encrypted:: + + ppstream_encrypted(stream) // macro, returns non-zero if encrypted + +Encryption is independent from compression, don't confuse with ``ppstream_compressed()`` + +Pages +----- + +Several helpers to deal with pages. To get the number of pages:: + + ppuint ppdoc_page_count (ppdoc *pdf); + +To access the root pages tree node:: + + ppref * ppdoc_pages(ppdoc *pdf); + +To get the page reference at a given index:: + + ppref * ppdoc_page (ppdoc *pdf, ppuint index); + +``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL. +Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration +would be suboptimal. Here is a dedicted iterator for this:: + + ppref * ppdoc_first_page (ppdoc *pdf); + ppref * ppdoc_next_page (ppdoc *pdf); + +The iterator in use:: + + ppdoc *pdf; + ppref *ref; + ppdict *dict; + int pageno; + + pdf = ppdoc_load("file.pdf"); + for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno) + { + dict = ppref_obj(obj)->dict; // take for granted it is a dict + // do something with the page dict + } + +Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity +type checks here. + +Contents +-------- + +PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page +contents streams:: + + ppstream * ppcontents_first (ppdict *dict); + ppstream * ppcontents_next (ppdict *dict, ppstream *stream); + +A complete example of contents stream parser use is given below (example 2). +But before we get there, we need to introduce ``ppcontext`` object. Conceptually, +``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``). +So far used only with contents stream parser, which might produce quite some data that we want +to release just after used. To create a new context:: + + pcontext * ppcontext_new (void); + +It initializes a new context and its internal memory heap, taking about 64kB on start. After that, +the context is ready to produce objects (contents parsing functions below). Once objects produced +from a given context are no longer needed:: + + void ppcontext_done (ppcontext *context); + +It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context +is ready to produce another bunch of beings (in the example below, all objects from the next page contents). +Once the context is not needed anymore:: + + void ppcontext_free (ppcontext *context); + +Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser +that allows to process the contents operator by operator:: + + ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + +Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack. +The operator itself is stored as ``*pname``. + +To parse the entire contents stream at once with no stop at every operator:: + + ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize); + +Returns probably quite long list of all parsed objects (operands and operatos) in one piece. +The number of objects is stored to ``*psize``. + +[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax:: + + BI ID EI + +Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string) +followed by ``EI`` operator name.] + +Boxes +----- + +Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum lx, ly, rx, ry; + } pprect; + +This type is used only by helper functions - PDF parser is not aware of the rectangle type. +To convert ``pparray`` to ``pprect``:: + + pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL + +In example:: + + pprect rect; + if (pparray_to_rect(array, &rect) != NULL) + ; // do something with rect + +To get some image bounding box:: + + pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_rect(imagedict, "BBox", &rect) + +To get some page box:: + + pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_box(pagedict, "MediaBox", &rect) + +The later not only checks the pagedict, but also goes through parent page nodes. + +Transforms +---------- + +Transformations are given as 6-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum xx, xy, yx, yy, x, y; + } ppmatrix; + +This type is used only by helper functions - PDF parser is not aware of the matrix type. +To convert ``pparray`` to ``ppmatrix``:: + + ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix); + +In example:: + + ppmatrix matrix; + if (pparray_to_matrix(array, &matrix) != NULL) + ; // do something with matrix + +To get the matrix from dict:: + + ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix); + // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix) + +Errors handling +--------------- + +``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing +of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.:: + + invalid 123 0 R object at offset 123123 + +To replace the default logger, you can provide your own:: + + void pplog_callback (pplogger_callback logger, void *alien); + +``pplogger_callback`` is a function:: + + void your_callback (const char *message, void *alien); + +In example, to redirect messages to stderr you may define a function:: + + void your_callback (const char *message, void *alien) + { + fprintf((FILE *)alien, "\nooops: %s\n", message); + } + +Then set the callback somewhere before loading documents:: + + pplog_callback(your_callback, stderr); + +(example 2 uses that). + +To set the default log messages prefix, eg. ``pplib:``, use:: + + int pplog_prefix (const char *prefix) + +Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes). diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt new file mode 100644 index 00000000000..250cd8fcd35 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt @@ -0,0 +1,937 @@ + +``pplib`` 2.x +============= + +``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C. + +C-API +===== + +Types +----- + +``pplib`` defines several C-types to represent PDF types: + +- ``ppbyte`` - char +- ``ppint`` - signed integer (``int64_t``) +- ``ppnum`` - real number (double) +- ``ppname`` - PDF name +- ``ppstring`` - PDF string +- ``pparray`` - PDF array +- ``ppdict`` - PDF dict +- ``ppstream`` - PDF stream +- ``ppref`` - PDF indirect reference +- ``ppobj`` - a container of all above + +Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``). + +Other API types: + +- ``ppdoc`` - PDF document +- ``ppxref`` - cross-references table +- ``ppcontext`` - ... later +- ``pprect`` - rectangle +- ``ppmatrix`` - matrix + +Integer and number are as simple types. Names and strings used to be aliases to ``char *`` +in ``pplib 1.x``, now they are structures; all related API functions operate on pointers. +Other types (array, dict, stream, reference, object container, xref, doc) are C-structures, +and you operate it their pointers. So when you declare a simple type variable you say:: + + ppuint u; + ppnum n; + ... + +And when you declare a compound type you operate on pointers:: + + ppobj *obj; + ppname *name; + ppstring *string; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + ppdoc *pdf; + +Most of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete +(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in +the header. The library itself uses ``pplib.h`` header but for auxilary applications including a standalone +``ppapi.h`` header should be enough. + +``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed, +so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because +then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library +internals to unconst. Besides, nothing is really const for C type casts. + +Object +------ + +A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier +(integer) and union of values:: + + struct ppobj { + ppobjtp type; + union { + ppint integer; + ppnum number; + ppname *name; + ppstring *string; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + void *any; + }; + }; + +Object type is one of constants (enum):: + + PPNONE + PPNULL + PPBOOL + PPINT + PPNUM + PPNAME + PPSTRING + PPARRAY + PPDICT + PPSTREAM + PPREF + +The type determines the structure member you're allowed to access:: + + ppobj *obj; + ... + switch (obj->type) + { + case PPNONE: // shouldn't actually happen, indicates some failure + break; + case PPNULL: // valid PDF null object, no value + break; + case PPBOOL: // do something with obj->integer (ppint), value 0 or 1 + break; + case PPINT: // do something with obj->integer (ppint) + break; + case PPNUM: // do something with obj->number (ppnum) + break; + case PPNAME: // do something with obj->name (ppname *) + break; + case PPSTRING: // do something with obj->string (ppstring *) + break; + case PPARRAY: // do something with obj->array (pparray *) + break; + case PPDICT: // do something with obj->dict (ppdict *) + break; + case PPSTREAM: // do something with obj->stream (ppstream *) + break; + case PPREF: // do something with obj->ref (ppref *) + break; + } + +More often then not you know exactly what type of object value is expected, in which case +you may use one of the following macros:: + + // returns 1 if o->type is PPNULL + int ppobj_get_null(o) \ + + // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise + int ppobj_get_bool(o, v) + + // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise + int ppobj_get_int(o, v) + + // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise + int ppobj_get_uint(o, v) + + // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise + int ppobj_get_num(o, v) + + // if o->type is PPNAME returns the name, NULL otherwise + ppname * ppobj_get_name(o) + + // if o->type is PPSTRING returns the string, NULL otherwise + ppstring * ppobj_get_string(o) + + // if o->type is PPARRAY returns the array, NULL otherwise + pparray * ppobj_get_array(o) + + // if o->type is PPDICT returns the dict, NULL otherwise + ppdict * ppobj_get_dict(o) + + // if o->type is PPSTREAM returns the stream, NULL otherwise + ppstream * ppobj_get_stream(o) + + // if o->type is PPREF returns the reference, NULL otherwise + ppref * ppobj_get_ref(o) + +Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number, +you should also handle integer (eg. '1' used instead of '1.0' is pretty common in PDF). + +It is a common case that the object is given as an indirect reference, but what you actually +want is not the reference, but the object referred by it. Here is a helper for it:: + + // if o->type is PPREF, returns what the reference points, otherwise returns o + ppobj * ppobj_rget_obj(o) + +Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check +for the expected type, but if the object is PPREF, it jumps to the target object. +So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT +or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT. + +Names +----- + +PDF names are represented as ``ppname`` pointer (``ppname`` used to be an alias to ``char *``, now it is a structure). +To access the name data:: + + ppbyte * ppname_data(name) // name->data, bytes array + +For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use +``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``:: + + size_t ppname_size(ppname name); // name->size, the length of name in bytes + +In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``. +Use macros:: + + int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string + int ppname_eq(ppname name, ppname other); // to compare ppname with a different name + +If you use ``pplib`` to parse contents streams, you may need to distinguish names from operators +(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both +cases PDF parser will produce ``ppname`` but the result can be distingushed with:: + + int ppname_exec(ppname name); // macro, returns non-zero if the name is executable + +Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form). +Leading '/' is omitted. One may need a decoded name, with no PDF escapes. +A pair of functions provides a simple interface to switch between those two forms:: + + // these helpers rely on name->alterego member + ppname * ppname_decoded (ppname *name); // returns decoded (unescaped) form of the name + ppname * ppname_encoded (ppname *name); // returns encoded (escaped) form of the name + ppbyte * ppname_decoded_data (ppname *name); + ppbyte * ppname_encoded_data (ppname *name); + +In pretty most cases a PDF name contains only letters (no special characters, no escapes), so decoded and encoded forms are identical. +In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form +and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego +in whatever direction needs no extra decoding or allocation costs (the cost is paid by parser). + +String +------ + +PDF strings have the same internal construction as names, so most of names description above applies to strings as well. +``ppstring`` is a structure (used to be an alias to ``char *``). ``string->data`` is ``\0``-terminated c-array of ``ppbytes``. +To get the data:: + + ppbyte * ppstring_data(ppstring *string); // string->data, macro + +To get the size of the string:: + + size_t ppstring_size(ppstring *string); // macro, returns the length of the string in bytes + +Strings are provided in their raw form, preserving PDF specific escapes, but with no +``()`` or ``<>`` delims. To distinguish plain strings from hex strings:: + + int ppstring_hex(ppstring string); // macro, returns non zero if hex string + +Or if you prefer:: + + switch (ppstring_type(string)) + { + case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF + break; + case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF + break; + case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF + break; + } + +The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams... +No matter how the string is given in PDF (plain or hex), here are two functions to +switch between encoded and decoded strings forms:: + + ppstring * ppstring_decoded (ppstring *string); // returns decoded string possibly with PDF escapes + ppstring * ppstring_encoded (ppstring *string); // returns encoded string with no PDF escapes + ppbyte * ppstring_decoded_data (ppstring *string); + ppbyte * ppstring_encoded_data (ppstring *string); + +For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding). +Plain strings usually contains printable ASCII characters, but they might contain any binary data. +As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) the main one. +Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego. + +No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string is unicode. +``ppstring`` object *knows* it is unicode or not:: + + switch (ppstring_utf(string)) + { + case PPSTRING_UTF16LE: // unicode string, utf16le + break; + case PPSTRING_UTF16BE: // unicode string, utf16be + break; + default: // no unicode + } + +Or simply:: + + if (ppstring_utf(string) != 0) { + // handle unicode string + } + +If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it. +Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()`` +always returns the size in bytes. + +Array +----- + +PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures. +To get the size:: + + size_t pparray_size(pparray *array) // macro, returns the number of array items + +To get ``ppobj *`` at a given index:: + + ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check) + ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check) + ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get() + +Iterating over array elements:: + + pparray *array; + size_t index, size; + ppobj *obj; + for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj)) + { + // do something with index and obj + } + +There is no magic first/next macros, just iteration over pointers. One could also use something like:: + + for (index = 0, size = array->size; index < size; ++index) + { + obj = pparray_at(array, index); + // do something with index and obj + } + +When getting values from array and expecting a result of known type, use one of the following:: + + int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value + int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value + int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value + int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value + ppname * pparray_get_name (pparray *array, size_t index); // get ppname * value + ppstring * pparray_get_string (pparray *array, size_t index); // get ppstring * value + pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value + ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value + ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value + +As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches. +Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL. + +Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart +that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that +there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect +(may only reside in ``ref->object.stream``). To get the stream from array use:: + + ppstream * pparray_rget_stream (pparray *array, size_t index); + +Dict +---- + +PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel +C-array of ``ppname`` pointers. To get the size of a dict:: + + size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs + +To get the value at a given index (integer):: + + ppobj * ppdict_at(ppdict *dict, index) // macro, no index bounds check + +To get the name (key) at a given index:: + + ppname * ppdict_key(ppdict *dict, index) // macro, no index bounds check + +To iterate over dict key-val pairs:: + + ppdict *dict; + ppname **pkey; + ppobj *obj; + + for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) + { + // do something with *pkey and obj + } + +There is no magic in first/next macros, just iteration through keys and values lists pointers. +For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL`` +is used as the loop condition. One may also iterate via indices:: + + ppdict *dict; + size_t index, size; + ppname *key; + ppobj *obj; + for (index = 0, size = ppdict_size(dict); index < size; ++index) + { + key = ppdict_key(dict, index); + obj = ppdict_at(dict, index); + // do something with key and obj + } + +To get the object associated with a given name, use one of the following:: + + ppobj * ppdict_get_obj (ppdict *dict, const char *name); + int ppdict_get_bool (ppdict *dict, const char *name, int *v); + int ppdict_get_int (ppdict *dict, const char *name, ppint *v); + int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v); + int ppdict_get_num (ppdict *dict, const char *name, ppnum *v); + ppname ppdict_get_name (ppdict *dict, const char *name); + ppstring ppdict_get_string (ppdict *dict, const char *name); + pparray * ppdict_get_array (ppdict *dict, const char *name); + ppdict * ppdict_get_dict (ppdict *dict, const char *name); + ppref * ppdict_get_ref (ppdict *dict, const char *name); + +Note that all getters accepts ``const char *`` as key, so it is ok to say:: + + ppdict_rget_dict(dict, "Resources"); + +(the most common use I guess). But to use ``ppname`` object as a key, one have to +use data member:: + + ppdic_rget_dict(dict, name->data); // ppname *name + +Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences +indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function, +but there is:: + + ppstream * ppdict_rget_stream (ppdict *dict, const char *name); + +So far dicts comes with no names mapping, so by-name dict accessors perform a linear search +through the keys list. PDF dicts are usually small. + +Stream +------ + +PDF streams are represented as ``ppstream`` objects. To get the stream dict:: + + ppdict * ppstream_dict(ppstream *stream) // macro + +To read the stream data:: + + uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode); + uint8_t * ppstream_next (ppstream *stream, size_t *size); + void ppstream_done (ppstream *stream); + +Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk. +``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()`` +must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``, +no matter if the stream has been read to the end or not. The stream data iterator in use:: + + uint8_t *data; + size_t size; + ppstream *stream; + int decode = 1; // 1 - get decompressed, 0 - get raw + + for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size)) + { + // do something with data and its size + } + ppstream_done(stream); + +Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk +of data just after you ot that. So the following is wrong:: + + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_next(stream, &size); + data3 = ppstream_next(stream, &size); + some_output(data1, size); + some_output(data2, size); + +The reader calls usually return the same pointer to internal buffer, just filled with a different data. +``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader. + +If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result. +You can check if the stream is actually compressed with:: + + ppstream_compressed(stream) // macro, returns non zero if /Filter is present + +It might be necessary to load the entire stream data at once:: + + uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode); + +If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call +``ppstream_done(stream)`` after using returned data. + +``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader. +The stream itself remains a valid object (eg. one can read it again if necessary), +but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream, +but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read. + +Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong:: + + data1 = ppstream_all(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_first(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + +To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``). +But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the +final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should +give the same results:: + + ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there + ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same + +A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``, +the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers. +``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats +some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects. +If you suffer from this, you can optionally use a pair of functions:: + + void ppstream_init_buffers (void); + void ppstream_free_buffers (void); + +The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader, +so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once +as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer. + +Filters +------- + +``ppstream`` knows its filter(s) and keps it as ``stream->filter``:: + + // ppstream *stream; + ppstream_filter *info = &stream->filter; + +``ppstream_filter`` is the following structure:: + + typedef struct { + ppstreamtp *filters; // c-array of filter identifiers (enum integers) + ppdict **params; // c-array of ppdict pointers + size_t count; // number of filters, length of the arrays (typically 1) + } ppstream_filter; + +If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants:: + + PPSTREAM_BASE16 /* /ASCIIHexDecode */ + PPSTREAM_BASE85 /* /ASCII85Decode */ + PPSTREAM_RUNLENGTH /* /RunLengthDecode */ + PPSTREAM_FLATE /* /FlateDecode */ + PPSTREAM_LZW /* /LZWDecode */ + PPSTREAM_CCITT /* /CCITTFaxDecode */ + PPSTREAM_DCT /* /DCTDecode */ + PPSTREAM_JBIG2 /* /JBIG2Decode */ + PPSTREAM_JPX /* /JPXDecode */ + PPSTREAM_CRYPT /* /Crypt */ + +Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL +if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there, +for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``). + +``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers +(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers:: + + void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode); + +The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows +how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF). + +To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name:: + + const char * ppstream_filter_name[]; + +To covert ``ppname`` to filter identifier:: + + int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype); + // returns 1 and sets filtertype if filtername is the proper filter name + +Additional information about the stream can be fetched from macros:: + + ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */ + ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */ + ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */ + +``stream->flags`` is a binary sum of the following:: + + PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */ + PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */ + PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */ + PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */ + +Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead. +And there is some more, see ``ppapi.h``. + +Ref +--- + +Indirect objects are represented as ``ppref`` structure. To get the object that the +reference refers to:: + + ppobj * ppref_obj(ppref *ref) // macro + +``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs +to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references +on-fly. So if there is a dict with indirect objects:: + + << + /Type /Page + /Resources 123 0 R + ... + >> + +the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value. +If you need more, access ``ppref`` members:: + + struct ppref { + ppobj object; // target object + ppuint number, version; // identifiers + size_t offset; // file offset (useless for you, may be zero for compressed objects) + ppuint length; // the length of the original object data + ppxref *xref; // cross reference table it belongs to + }; + + +XRef +---- + +Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer). +To get top document xref:: + + ppxref * ppdoc_xref (ppdoc *pdf); + +To get previous (older) xref:: + + ppxref * ppxref_prev (ppxref *xref); + +To find an object of a given refnumber:: + + ppref * ppxref_find (ppxref *xref, ppuint refnumber); + +[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns +the newest available version of a given object rather than the object in a given body.] + +PDF +--- + +PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer). +To load a document from file:: + + ppdoc * ppdoc_load (const char *filename); + +To load a document from file handle:: + + ppdoc * ppdoc_filehandle (FILE *file, int closefile); // closefile 1 to fclose() on end + +To load a document from memory data:: + + ppdoc * ppdoc_mem (const void *data, size_t size); + +The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``. + +Both loaders returns ``NULL`` on failure. + +To free ``ppdoc`` and all objects it refers to:: + + void ppdoc_free (ppdoc *pdf); + +So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions +for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all +beings it refers to. It also means that every object described so far is alive as long as the containing +``ppdoc`` is alive. + +To access main PDF dicts:: + + ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict + ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer + ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer + +To get the PDF version:: + + const char * ppdoc_version_string (ppdoc *pdf); // version string + int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers + +To get the file size of the source PDF document:: + + size_t ppdoc_file_size (ppdoc *pdf); + +To get the number of objects in all xrefs:: + + ppuint ppdoc_objects (ppdoc *pdf); + +To get the approx usage of memory:: + + size_t ppdoc_memory (ppdoc *pdf, size_t *waste); + +Encryption +---------- + +``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered. +In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output. +It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting +for a password), but some features (eg. printing) may restricted by the application. + +When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing +an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives +a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries +set to ``null``. + +After loading a document you should check encryption status with:: + + ppcrypt_status ppdoc_crypt_status (ppdoc *pdf); + +``ppcrypt_status`` (integer) may have the following values: + + ``PPCRYPT_NONE`` - no encryption, go ahead + ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead + ``PPCRYPT_PASS`` - encryption present, need non-empty password + ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec) + +If a password is needed, you can provide one with:: + + ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength, + const void *ownerpass, size_t ownerpasslength); + +Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough +to know that having one of them is enough to decrypt the document. If you know the password, you probably mean +``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password +succeeds and the previous status otherwise. Your custom loader function may look like that:: + + ppdoc *pdf; + pdf = ppdoc_load("file.pdf"); + if (pdf == NULL) + return NULL; + switch (ppdoc_crypt_status(pdf)) + { + case PPCRYPT_NONE: + case PPCRYPT_DONE: + return pdf; + case PPCRYPT_PASS: + if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || + ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE) + return pdf; + printf("sorry, password needed\n"); + ppdoc_free(pdf); + return NULL; + case PPCRYPT_FAIL: + printf("sorry, encryption failed\n"); + ppdoc_free(pdf); + return NULL; + } + +[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.] + +If you'd like to know what permissions are given/restricted to encrypted document:: + + ppint ppdoc_permissions (ppdoc *pdf); + +Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab):: + + PPDOC_ALLOW_PRINT // printing + PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages + PPDOC_ALLOW_COPY // copying, copying for accessibility + PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing + PPDOC_ALLOW_EXTRACT // contents copying for accessibility + PPDOC_ALLOW_ASSEMBLY // (no effect) + PPDOC_ALLOW_PRINT_HIRES // (no effect) + +``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings +and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered). +Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted. +So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption. + +In encrypted documents most of streams are encrypted. To check if a given stream is encrypted:: + + ppstream_encrypted(stream) // macro, returns non-zero if encrypted + +Encryption is independent from compression, don't confuse with ``ppstream_compressed()`` + +Pages +----- + +Several helpers to deal with pages. To get the number of pages:: + + ppuint ppdoc_page_count (ppdoc *pdf); + +To access the root pages tree node:: + + ppref * ppdoc_pages(ppdoc *pdf); + +To get the page reference at a given index:: + + ppref * ppdoc_page (ppdoc *pdf, ppuint index); + +``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL. +Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration +would be suboptimal. Here is a dedicted iterator for this:: + + ppref * ppdoc_first_page (ppdoc *pdf); + ppref * ppdoc_next_page (ppdoc *pdf); + +The iterator in use:: + + ppdoc *pdf; + ppref *ref; + ppdict *dict; + int pageno; + + pdf = ppdoc_load("file.pdf"); + for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno) + { + dict = ppref_obj(obj)->dict; // take for granted it is a dict + // do something with the page dict + } + +Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity +type checks here. + +Contents +-------- + +PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page +contents streams:: + + ppstream * ppcontents_first (ppdict *dict); + ppstream * ppcontents_next (ppdict *dict, ppstream *stream); + +A complete example of contents stream parser use is given below (example 2). +But before we get there, we need to introduce ``ppcontext`` object. Conceptually, +``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``). +So far used only with contents stream parser, which might produce quite some data that we want +to release just after used. To create a new context:: + + pcontext * ppcontext_new (void); + +It initializes a new context and its internal memory heap, taking about 64kB on start. After that, +the context is ready to produce objects (contents parsing functions below). Once objects produced +from a given context are no longer needed:: + + void ppcontext_done (ppcontext *context); + +It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context +is ready to produce another bunch of beings (in the example below, all objects from the next page contents). +Once the context is not needed anymore:: + + void ppcontext_free (ppcontext *context); + +Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser +that allows to process the contents operator by operator:: + + ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + +Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack. +The operator itself is stored as ``*pname``. + +To parse the entire contents stream at once with no stop at every operator:: + + ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize); + +Returns probably quite long list of all parsed objects (operands and operatos) in one piece. +The number of objects is stored to ``*psize``. + +[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax:: + + BI ID EI + +Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string) +followed by ``EI`` operator name.] + +Boxes +----- + +Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum lx, ly, rx, ry; + } pprect; + +This type is used only by helper functions - PDF parser is not aware of the rectangle type. +To convert ``pparray`` to ``pprect``:: + + pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL + +In example:: + + pprect rect; + if (pparray_to_rect(array, &rect) != NULL) + ; // do something with rect + +To get some image bounding box:: + + pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_rect(imagedict, "BBox", &rect) + +To get some page box:: + + pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_box(pagedict, "MediaBox", &rect) + +The later not only checks the pagedict, but also goes through parent page nodes. + +Transforms +---------- + +Transformations are given as 6-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum xx, xy, yx, yy, x, y; + } ppmatrix; + +This type is used only by helper functions - PDF parser is not aware of the matrix type. +To convert ``pparray`` to ``ppmatrix``:: + + ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix); + +In example:: + + ppmatrix matrix; + if (pparray_to_matrix(array, &matrix) != NULL) + ; // do something with matrix + +To get the matrix from dict:: + + ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix); + // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix) + +Errors handling +--------------- + +``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing +of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.:: + + invalid 123 0 R object at offset 123123 + +To replace the default logger, you can provide your own:: + + void pplog_callback (pplogger_callback logger, void *alien); + +``pplogger_callback`` is a function:: + + void your_callback (const char *message, void *alien); + +In example, to redirect messages to stderr you may define a function:: + + void your_callback (const char *message, void *alien) + { + fprintf((FILE *)alien, "\nooops: %s\n", message); + } + +Then set the callback somewhere before loading documents:: + + pplog_callback(your_callback, stderr); + +(example 2 uses that). + +To set the default log messages prefix, eg. ``pplib:``, use:: + + int pplog_prefix (const char *prefix) + +Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes). diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi.rst.txt new file mode 100644 index 00000000000..5d1d2883e57 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi.rst.txt @@ -0,0 +1,937 @@ + +``pplib`` +========= + +``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C. + +C-API +===== + +Types +----- + +``pplib`` defines several C-types to represent PDF types: + +- ``ppint`` - signed integer (``int64_t``) +- ``ppnum`` - real number (double) +- ``ppname`` - PDF name +- ``ppstring`` - PDF string +- ``pparray`` - PDF array +- ``ppdict`` - PDF dict +- ``ppstream`` - PDF stream +- ``ppref`` - PDF indirect reference +- ``ppobj`` - a container of all above + +Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``). + +Other API types: + +- ``ppdoc`` - PDF document +- ``ppxref`` - cross-references table +- ``ppcontext`` - ... later +- ``pprect`` - rectangle +- ``ppmatrix`` - matrix + +Integer, number, name and string are treated as simple types. +Names and strings are actually C-structures, but exposed to API as typedefs to ``const char *``. +Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures, +and you operate it their pointers. So when you declare a simple type variable you say:: + + ppuint u; + ppnum n; + ppname name; + ppstring string; + ... + +And when you declare a compound type you operate on pointers:: + + ppobj *obj; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + ppdoc *pdf; + +Some of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete +(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in +the header. [At some points it's not clear to me what to hide and what to expose, will see.] The library itself +uses ``pplib.h`` but for auxilary applications including a standalone ``ppapi.h`` header should be enough. + +``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed, +so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because +then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library +internals to unconst. Besides, nothing is really const for C type casts. + +Object +------ + +A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier +(integer) and union of values:: + + struct ppobj { + ppobjtp type; + union { + ppint integer; + ppnum number; + ppname name; + ppstring string; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + void *any; + }; + }; + +Object type is one of constants (enum):: + + PPNONE + PPNULL + PPBOOL + PPINT + PPNUM + PPNAME + PPSTRING + PPARRAY + PPDICT + PPSTREAM + PPREF + +The type determines the structure member you're allowed to access:: + + ppobj *obj; + ... + switch (obj->type) + { + case PPNONE: // shouldn't actually happen, indicates some failure + break; + case PPNULL: // valid PDF null object, no value + break; + case PPBOOL: // do something with obj->integer (ppint), value 0 or 1 + break; + case PPINT: // do something with obj->integer (ppint) + break; + case PPNUM: // do something with obj->number (ppnum) + break; + case PPNAME: // do something with obj->name (ppname) + break; + case PPSTRING: // do something with obj->string (ppstring) + break; + case PPARRAY: // do something with obj->array (pparray *) + break; + case PPDICT: // do something with obj->dict (ppdict *) + break; + case PPSTREAM: // do something with obj->stream (ppstream *) + break; + case PPREF: // do something with obj->ref (ppref *) + break; + } + +More often then not you know exactly what type of object value is expected, in which case +you may use one of the following macros:: + + // returns 1 if o->type is PPNULL + int ppobj_get_null(o) \ + + // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise + int ppobj_get_bool(o, v) + + // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise + int ppobj_get_int(o, v) + + // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise + int ppobj_get_uint(o, v) + + // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise + int ppobj_get_num(o, v) + + // if o->type is PPNAME returns the name, NULL otherwise + ppname ppobj_get_name(o) + + // if o->type is PPSTRING returns the string, NULL otherwise + ppstring ppobj_get_string(o) + + // if o->type is PPARRAY returns the array, NULL otherwise + pparray * ppobj_get_array(o) + + // if o->type is PPDICT returns the dict, NULL otherwise + ppdict * ppobj_get_dict(o) + + // if o->type is PPSTREAM returns the stream, NULL otherwise + ppstream * ppobj_get_stream(o) + + // if o->type is PPREF returns the reference, NULL otherwise + ppref * ppobj_get_ref(o) + +Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number, +you should also handle integer (eg. '1' used instead of '1.0'). + +It is a common case that the object is given as an indirect reference, but what you actually +want is not the reference, but the object referred by it. Here is a helper for it:: + + // if o->type is PPREF, returns what the reference points, otherwise returns o + ppobj * ppobj_rget_obj(o) + +Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check +for the expected type, but if the object is PPREF, it jumps to the target object. +So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT +or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT. + +Names +----- + +PDF names are represented as ``ppname``. +I find it convenient to have ``ppname`` type pretending ``const char *``. This allows to use ``ppname`` +in all C-style string functions like ``printf("%s", name)``. + +Be aware, however, that ``ppname`` is actually a C-structure. It is perfectly ok to cast ``ppname`` to ``const char *``:: + + ppname name; + ... + (const char *)name; + +But reverse is forbidden:: + + const char *cstr = "cstring"; + ... + (ppname)cstr; // expect segmentation fault soon + +For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use +``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``:: + + size_t ppname_size(ppname name); // macro, returns length of name in bytes + +In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``. +Use macros:: + + int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string + int ppname_eq(ppname name, ppname other); // to compare ppname with a different name + +If you'll use ``pplib`` to parse contents streams, you may need to distinguish names from operators +(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both +cases PDF parser will produce ``ppname`` but can be distingushed with:: + + int ppname_exec(ppname name); // returns non-zero if name is executable + +Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form). +Leading '/' is omitted, though. One may need a decoded name, with no PDF escapes. +A pair of functions provides a simple interface to switch between those two forms:: + + ppname ppname_decoded (ppname name); // returns decoded (unescaped) form of the name + ppname ppname_encoded (ppname name); // returns encoded (escaped) form of the name + +In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical. +In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form +and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego +in whatever direction needs no extra decoding or allocation costs. + +String +------ + +PDF strings have the same internal construction as names, so most of names description above applies to strings as well. +``ppstring`` is a typedef of ``const char *``, roughly ``'\0'`` terminiated C-string. To get the size of the string:: + + size_t ppstring_size(ppstring string); // macro, returns the length of the string in bytes + +Strings are provided in their raw form, preserving PDF specific escapes, but with no +``()`` or ``<>`` delims. To distinguish plain strings from hex strings:: + + int ppstring_hex(ppstring string); // macro, returns non zero if hex string + +Or if you prefer:: + + switch (ppstring_type(string)) + { + case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF + break; + case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF + break; + case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF + break; + } + +The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams... +No matter how the string is given in PDF (plain or hex), here are two functions to +switch between encoded and decoded strings forms:: + + ppstring ppstring_decoded (ppstring string); // returns decoded string possibly with PDF escapes + ppstring ppstring_encoded (ppstring string); // returns encoded string with no PDF escapes + +For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding). +Plain strings usually contains printable ASCII characters, but they might contain any binary data. +As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one. +Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego. + +No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string +is considered unicode. ``ppstring`` object *knows* it is unicode or not:: + + switch (ppstring_utf(string)) + { + case PPSTRING_UTF16LE: // unicode string, utf16le + break; + case PPSTRING_UTF16BE: // unicode string, utf16be + break; + default: // no unicode + } + +Or simply:: + + if (ppstring_utf(string) != 0) { + // handle unicode string + } + +If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it. +Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()`` +always returns the size in bytes. + +Array +----- + +PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures. +To get the size:: + + size_t pparray_size(pparray *array) // macro, returns the number of array items + +To get ``ppobj *`` at a given index:: + + ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check) + ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check) + ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get() + +Iterating over array elements:: + + pparray *array; + size_t index, size; + ppobj *obj; + for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj)) + { + // do something with index and obj + } + +There is no magic first/next macros, just iteration over pointers. One could also use something like:: + + for (index = 0, size = array->size; index < size; ++index) + { + obj = pparray_at(array, index); + // do something with index and obj + } + +When getting values from array and expecting a result of known type, use one of the following:: + + int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value + int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value + int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value + int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value + ppname pparray_get_name (pparray *array, size_t index); // get ppname value + ppstring pparray_get_string (pparray *array, size_t index); // get ppstring value + pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value + ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value + ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value + +As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches. +Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL. + +Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart that +that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that +there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect. +To get the stream from array use:: + + ppstream * pparray_rget_stream (pparray *array, size_t index); + +Dict +---- + +PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel +C-array of ``ppname`` pointers. To get the size of a dict:: + + size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs + +To get the value at a given index (integer):: + + ppobj * ppdict_at(ppdict *dict, index) // macro, no index check + +To get the name (key) at a given index:: + + ppname ppdict_key(ppdict *dict, index) // macro, no index check + +To iterate over dict key-val pairs:: + + ppdict *dict; + ppname *pkey; + ppobj *obj; + + for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) + { + // do something with *pkey and obj + } + +There is no magic in first/next macros, just iteration through keys and values lists pointers. +For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL`` +is used as the loop condition. One may also iterate via indices:: + + ppdict *dict; + size_t index, size; + ppname key; + ppobj *obj; + for (index = 0, size = ppdict_size(dict); index < size; ++index) + { + key = ppdict_key(dict, index); + obj = ppdict_at(dict, index); + // do something with key and obj + } + +To get the object associated with a given name, use one of the following:: + + ppobj * ppdict_get_obj (ppdict *dict, const char *name); + int ppdict_get_bool (ppdict *dict, const char *name, int *v); + int ppdict_get_int (ppdict *dict, const char *name, ppint *v); + int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v); + int ppdict_get_num (ppdict *dict, const char *name, ppnum *v); + ppname ppdict_get_name (ppdict *dict, const char *name); + ppstring ppdict_get_string (ppdict *dict, const char *name); + pparray * ppdict_get_array (ppdict *dict, const char *name); + ppdict * ppdict_get_dict (ppdict *dict, const char *name); + ppref * ppdict_get_ref (ppdict *dict, const char *name); + +Note that all getters accepts ``const char *`` as key, so it is ok to say:: + + ppdict_rget_dict(dict, "Resources"); + +as well as:: + + ppdic_rget_dict(dict, name); // ppname name + +Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences +indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function, +but there is:: + + ppstream * ppdict_rget_stream (ppdict *dict, const char *name); + +So far dicts comes with no names mapping, so by-name dict accessors perform a linear search +through the keys list. PDF dicts are usually small, so it is fast enough. +Building names lookup for every dict in PDF makes no sense I think, as ``pplib`` applications +will query just several dicts I guess.. However, some apps may extensively query +resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts +is still considered. + +Stream +------ + +PDF streams are represented as ``ppstream`` objects. To get the stream dict:: + + ppdict * ppstream_dict(ppstream *stream) // macro + +To read the stream data:: + + uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode); + uint8_t * ppstream_next (ppstream *stream, size_t *size); + void ppstream_done (ppstream *stream); + +Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk. +``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()`` +must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``, +no matter if the stream has been read to the end or not. The stream data iterator in use:: + + uint8_t *data; + size_t size; + ppstream *stream; + int decode = 1; // 1 - get decompressed, 0 - get raw + + for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size)) + { + // do something with data and its size + } + ppstream_done(stream); + +Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk +of data just after you ot that. So the following is wrong:: + + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_next(stream, &size); + data3 = ppstream_next(stream, &size); + some_output(data1, size); + some_output(data2, size); + +The reader calls usually return the same pointer to internal buffer, just filled with a different data. +``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader. + +If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result. +You can check if the stream is actually compressed with:: + + ppstream_compressed(stream) // macro, returns non zero if /Filter is present + +It might be necessary to load the entire stream data at once:: + + uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode); + +If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call +``ppstream_done(stream)`` after using returned data. + +``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader. +The stream itself remains a valid object (eg. one can read it again if necessary), +but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream, +but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read. + +Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong:: + + data1 = ppstream_all(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_first(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + +To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``). +But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the +final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should +give the same results:: + + ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there + ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same + +A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``, +the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers. +``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats +some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects. +If you suffer from this, you can optionally use a pair of functions:: + + void ppstream_init_buffers (void); + void ppstream_free_buffers (void); + +The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader, +so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once +as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer. + +Filters +------- + +In version v1.00 (20190916) ``ppstream`` API has been extended with filters information. +``ppstream`` knows its filter(s) and keps it as ``stream->filter``:: + + // ppstream *stream; + ppstream_filter *info = &stream->filter; + +``ppstream_filter`` is the following structure:: + + typedef struct { + ppstreamtp *filters; // c-array of filter identifiers (enum integers) + ppdict **params; // c-array of ppdict pointers + size_t count; // number of filters, length of the arrays (typically 1) + } ppstream_filter; + +If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants:: + + PPSTREAM_BASE16 /* /ASCIIHexDecode */ + PPSTREAM_BASE85 /* /ASCII85Decode */ + PPSTREAM_RUNLENGTH /* /RunLengthDecode */ + PPSTREAM_FLATE /* /FlateDecode */ + PPSTREAM_LZW /* /LZWDecode */ + PPSTREAM_CCITT /* /CCITTFaxDecode */ + PPSTREAM_DCT /* /DCTDecode */ + PPSTREAM_JBIG2 /* /JBIG2Decode */ + PPSTREAM_JPX /* /JPXDecode */ + PPSTREAM_CRYPT /* /Crypt */ + +Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL +if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there, +for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``). + +``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers +(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers:: + + void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode); + +The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows +how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF). + +To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name:: + + const char * ppstream_filter_name[]; + +To covert ``ppname`` to filter identifier:: + + int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype); + // returns 1 and sets filtertype if filtername is the proper filter name + +Additional information about the stream can be fetched from macros:: + + ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */ + ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */ + ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */ + +``stream->flags`` is a binary sum of the following:: + + PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */ + PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */ + PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */ + PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */ + +Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead. +And there is some more, see ``ppapi.h``. + +Ref +--- + +Indirect objects are represented as ``ppref`` structure. To get the object that the +reference refers to:: + + ppobj * ppref_obj(ppref *ref) // macro + +``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs +to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references +on-fly. So if there is a dict with indirect objects:: + + << + /Type /Page + /Resources 123 0 R + ... + >> + +the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value. +If you need more, access ``ppref`` members:: + + struct ppref { + ppobj object; // target object + ppuint number, version; // identifiers + size_t offset; // file offset (useless for you, may be zero for compressed objects) + ppuint length; // the length of the original object data + ppxref *xref; // cross reference table it belongs to + }; + + +XRef +---- + +Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer). +To get top document xref:: + + ppxref * ppdoc_xref (ppdoc *pdf); + +To get previous (older) xref:: + + ppxref * ppxref_prev (ppxref *xref); + +To find an object of a given refnumber:: + + ppref * ppxref_find (ppxref *xref, ppuint refnumber); + +[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns +the newest available version of a given object rather than the object in a given body.] + +PDF +--- + +PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer). +To load a document from file:: + + ppdoc * ppdoc_load (const char *filename); + +To load a document from memory data:: + + ppdoc * ppdoc_mem (const void *data, size_t size); + +The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``. + +Both loaders returns ``NULL`` on failure. + +To free ``ppdoc`` and all objects it refers to:: + + void ppdoc_free (ppdoc *pdf); + +So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions +for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all +beings it refers to. It also means that every object described so far is alive as long as the containing +``ppdoc`` is alive. + +To access main PDF dicts:: + + ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict + ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer + ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer + +To get the PDF version:: + + const char * ppdoc_version_string (ppdoc *pdf); // version string + int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers + +To get the file size of the source PDF document:: + + size_t ppdoc_file_size (ppdoc *pdf); + +To get the number of objects in all xrefs:: + + ppuint ppdoc_objects (ppdoc *pdf); + +To get the approx usage of memory:: + + size_t ppdoc_memory (ppdoc *pdf, size_t *waste); + +Encryption +---------- + +``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered. +In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output. +It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting +for a password), but some features (eg. printing) may restricted by the application. + +When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing +an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives +a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries +set to ``null``. + +After loading a document you should check encryption status with:: + + ppcrypt_status ppdoc_crypt_status (ppdoc *pdf); + +``ppcrypt_status`` (integer) may have the following values: + + ``PPCRYPT_NONE`` - no encryption, go ahead + ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead + ``PPCRYPT_PASS`` - encryption present, need non-empty password + ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec) + +If a password is needed, you can provide one with:: + + ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength, + const void *ownerpass, size_t ownerpasslength); + +Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough +to know that having one of them is enough to decrypt the document. If you know the password, you probably mean +``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password +succeeds and the previous status otherwise. Your custom loader function may look like that:: + + ppdoc *pdf; + pdf = ppdoc_load("file.pdf"); + if (pdf == NULL) + return NULL; + switch (ppdoc_crypt_status(pdf)) + { + case PPCRYPT_NONE: + case PPCRYPT_DONE: + return pdf; + case PPCRYPT_PASS: + if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || + ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE) + return pdf; + printf("sorry, password needed\n"); + ppdoc_free(pdf); + return NULL; + case PPCRYPT_FAIL: + printf("sorry, encryption failed\n"); + ppdoc_free(pdf); + return NULL; + } + +[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.] + +If you'd like to know what permissions are given/restricted to encrypted document:: + + ppint ppdoc_permissions (ppdoc *pdf); + +Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab):: + + PPDOC_ALLOW_PRINT // printing + PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages + PPDOC_ALLOW_COPY // copying, copying for accessibility + PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing + PPDOC_ALLOW_EXTRACT // contents copying for accessibility + PPDOC_ALLOW_ASSEMBLY // (no effect) + PPDOC_ALLOW_PRINT_HIRES // (no effect) + +``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings +and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered). +Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted. +So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption. + +In encrypted documents most of streams are encrypted. To check if a given stream is encrypted:: + + ppstream_encrypted(stream) // macro, returns non-zero if encrypted + +Encryption is independent from compression, don't confuse with ``ppstream_compressed()`` + +Pages +----- + +Several helpers to deal with pages. To get the number of pages:: + + ppuint ppdoc_page_count (ppdoc *pdf); + +To access the root pages tree node:: + + ppref * ppdoc_pages(ppdoc *pdf); + +To get the page reference at a given index:: + + ppref * ppdoc_page (ppdoc *pdf, ppuint index); + +``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL. +Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration +would be suboptimal. Here is a dedicted iterator for this:: + + ppref * ppdoc_first_page (ppdoc *pdf); + ppref * ppdoc_next_page (ppdoc *pdf); + +The iterator in use:: + + ppdoc *pdf; + ppref *ref; + ppdict *dict; + int pageno; + + pdf = ppdoc_load("file.pdf"); + for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno) + { + dict = ppref_obj(obj)->dict; // take for granted it is a dict + // do something with the page dict + } + +Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity +type checks here. + +Contents +-------- + +PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page +contents streams:: + + ppstream * ppcontents_first (ppdict *dict); + ppstream * ppcontents_next (ppdict *dict, ppstream *stream); + +A complete example of contents stream parser use is given below (example 2). +But before we get there, we need to introduce ``ppcontext`` object. Conceptually, +``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``). +So far used only with contents stream parser, which might produce quite some data that we want +to release just after used. To create a new context:: + + pcontext * ppcontext_new (void); + +It initializes a new context and its internal memory heap, taking about 64kB on start. After that, +the context is ready to produce objects (contents parsing functions below). Once objects produced +from a given context are no longer needed:: + + void ppcontext_done (ppcontext *context); + +It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context +is ready to produce another bunch of beings (in the example below, all objects from the next page contents). +Once the context is not needed anymore:: + + void ppcontext_free (ppcontext *context); + +Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser +that allows to process the contents operator by operator:: + + ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + +Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack. +The operator itself is stored as ``*pname``. + +To parse the entire contents stream at once with no stop at every operator:: + + ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize); + +Returns probably quite long list of all parsed objects (operands and operatos) in one piece. +The number of objects is stored to ``*psize``. + +[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax:: + + BI ID EI + +Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string) +followed by ``EI`` operator name.] + +Boxes +----- + +Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum lx, ly, rx, ry; + } pprect; + +This type is used only by helper functions - PDF parser is not aware of the rectangle type. +To convert ``pparray`` to ``pprect``:: + + pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL + +In example:: + + pprect rect; + if (pparray_to_rect(array, &rect) != NULL) + ; // do something with rect + +To get some image bounding box:: + + pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_rect(imagedict, "BBox", &rect) + +To get some page box:: + + pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_box(pagedict, "MediaBox", &rect) + +The later not only checks the pagedict, but also goes through parent page nodes. + +Transforms +---------- + +Transformations are given as 6-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum xx, xy, yx, yy, x, y; + } ppmatrix; + +This type is used only by helper functions - PDF parser is not aware of the matrix type. +To convert ``pparray`` to ``ppmatrix``:: + + ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix); + +In example:: + + ppmatrix matrix; + if (pparray_to_matrix(array, &matrix) != NULL) + ; // do something with matrix + +To get the matrix from dict:: + + ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix); + // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix) + +Errors handling +--------------- + +``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing +of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.:: + + invalid 123 0 R object at offset 123123 + +To replace the default logger, you can provide your own:: + + void pplog_callback (pplogger_callback logger, void *alien); + +``pplogger_callback`` is a function:: + + void your_callback (const char *message, void *alien); + +In example, to redirect messages to stderr you may define a function:: + + void your_callback (const char *message, void *alien) + { + fprintf((FILE *)alien, "\nooops: %s\n", message); + } + +Then set the callback somewhere before loading documents:: + + pplog_callback(your_callback, stderr); + +(example 2 uses that). + +To set the default log messages prefix, eg. ``pplib:``, use:: + + int pplog_prefix (const char *prefix) + +Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes). diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt new file mode 100644 index 00000000000..ebe92465d80 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt @@ -0,0 +1,101 @@ +Examples +======== + +Example 1 +--------- + +.. literalinclude:: ../src/pptest1.c + +Example 2 +--------- + +.. literalinclude:: ../src/pptest2.c + +Example 3 +--------- + +.. literalinclude:: ../src/pptest3.c + +ppapi.h +------- + +.. literalinclude:: ../src/ppapi.h + + +Changes +======= + +v0.97 +----- +First release integrated with luatex sources, plus portability changes from Luigi. + +v0.98 +----- +Changed references resolving in case of incremental updates; tech notes ppxref_find() in ppxref.c. + +v0.99 +----- +Fixed streams handling; null characters should NOT be gobbled after "stream" keyword + +v1.00 +----- +Fixed streams handling (Luigi); object streams updated before other streams +Revised streams handling, ppstream API extended + +v1.01 +----- +Fixed names handling (thanks Hans); digits after '#' weren't skipped + +v1.02 +----- +Fixed page finder (thanks Luigi) + +v1.03 +----- +Fixed TIFF predictor (thanks folks) + +v1.04 +----- +Fixed TIFF predictor for ARM + +v1.05 +----- +Attempt to fix parsing inline images crap + +v2.00 +----- +Deep rework on allocators. +Deep rework on strings and names. + +v2.01 +----- +Fixed invalid stream buffer handling; ``iof_discard()`` no longer reclaims the source (``filter->next``) filter. +Sanity alignment adjustments in ``iof_heap``. + +v2.02 +----- +Fixed incorrect encoding of strings alterego with octal escaping, thanks Luigi. +On Hans request added ``ppdoc_filehandle()`` function and ``ppdoc_file()`` macro for loading ppdoc from ``FILE *``. + +v2.03 +----- +Fixed alloc/free of ``ppdoc`` heap; ``ppdoc`` is now mallocated, no longer taken from its own heap. Again, thanks Luigi. +Fixed warnings about dereferencing type-puned pointers, and some others. + +v2.04 +----- +Byte lookups for names/strings loaders are now int8_t, as char might be signed. +ppdoc_first_page() / ppdoc_next_page() iterator now handles a case when /Kids array is empty. +Fixed generating keys for encrypted streams; ppstring_internal() returns the string of the proper size. +More stream tests in pptest3.c. +Some rework on md5 and sha2. + +v2.05 +----- +uint8_t instead of ppbyte in internals; ppbyte intent is "the most natural 8-bit integer", so it is 'char', +but internally we almost always need uint8_t (char may be signed or not..) + +TODO +==== +- external streams (egzotic) + diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/pplib.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/pplib.rst.txt new file mode 100644 index 00000000000..763dc79cf62 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/pplib.rst.txt @@ -0,0 +1,15 @@ +.. pplib documentation master file, created by + sphinx-quickstart on Thu Jun 07 14:23:51 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +pplib +===== + +.. toctree:: + :maxdepth: 2 + + ppnew + ppapi-2.x + ppapi-1.x + ppcode diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppnew.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppnew.rst.txt new file mode 100644 index 00000000000..4a0a3b42887 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppnew.rst.txt @@ -0,0 +1,103 @@ + +1.x vs 2.x +========== + +Allocation +---------- + +Allocation mechanisms has been revised. All objects are still allocated from a private storage (called heap), +but now the heap serves properly aligned memory chunks. Implementation of the heap is (hopefully) platform +independent, so all ``ARM_COMPLIANT`` checks has been removed. Some details work differently on 32/64-bit +machines, this distinction seems inevitable. Allocation related code has been moved to ``util/utilmem*.c`` files. + +[There are actually 3 different allocators - **heap**, **stock**, and **pool** - each of which has 4 variants +for 1, 2, 4 and 8 bytes alignment. So far ``pplib`` uses only the **heap**, but I want to have this part +in a single place for a while. More notes about allocators in ``utilmemallc.h``.] + +``pplib`` uses two heaps: + +* bytes heap - providing 2-bytes aligned memory chunks for byte data +* structures heap - providing 8-bytes aligned chunks for all structures + +2-bytes alignment of byte data is caused by implementation details / limits, ``pplib`` doesn't make a use of it +(could be unaligned as well). All the structures are stored in 8-bytes aligned chunks on both 32 and 64-bit machines +(in some structures we use ``double`` and ``int64_t``, which generally needs 8-bytes). + +Strings And Names +----------------- + +So far, both ``ppname`` and ``ppstring`` were aliases to ``char *`` with an extra structure hidden just below +the data address. The idea was to make a string or name usable whenever chars array can, at the cost of some +pointers trickery. Both names and strings keep an information about pdf-encoded data, as well as plain bytes data. +I implemented this feature once ``pplib 1.0`` was almost done, and to avoid a revolution, I made that with yet +another trick. This all was dirty and caused lots of alignment issues. + +Now ``ppstring`` and ``ppname`` are **structures**, keeping data and size members, pretty much like ``pparray``:: + + struct ppname { + ppbyte *data; + size_t size; + ppname *alterego; + int flags; + }; + + struct ppstring { + ppbyte *data; + size_t size; + ppstring *alterego; + int flags; + }; + +Data member is a pointer to (2-bytes aligned) bytes array -- ``ppbyte *``. ``ppbyte`` is an alias to ``char``. +``pplib`` makes no assumptions about ``ppbyte`` signedness. [I'd prefer to have ``uint8_t``, but better +keep that in sync with ``ppdict_get_*`` suite, which accepts ``char *``. Using ``"string literals"`` +with ``ppdict_get`` function is the most common case, I guess.] + +``ppname_size()`` and ``ppstring_size() `` now have +trivial ``ppname_data()`` and ``ppstring_data()`` counterparts:: + + #define ppname_size(name) ((name)->size) + #define ppname_data(name) ((name)->data) + + #define ppstring_size(string) ((string)->size) + #define ppstring_data(string) ((string)->data) + +Switching between encoded / decoded variants is made via explicit ``alterego`` member. If encoded and decoded forms +are identical, then ``self->alfterego == self`` (never NULL). Helper functions for that:: + + PPAPI ppname * ppname_decoded (ppname *name); + PPAPI ppname * ppname_encoded (ppname *name); + + PPAPI ppbyte * ppname_decoded_data (ppname *name); + PPAPI ppbyte * ppname_encoded_data (ppname *name); + + PPAPI ppstring * ppstring_decoded (ppstring *string); + PPAPI ppstring * ppstring_encoded (ppstring *string); + + PPAPI ppbyte * ppstring_decoded_data (ppstring *string); + PPAPI ppbyte * ppstring_encoded_data (ppstring *string); + +Since ``ppname`` and ``ppstring`` are now structures, all API functions returning name/string or taking name/string +as an argument, now take **a pointer to name/string**. Watch out for ``ppdict_get_*`` functions suite. They still accept +``const char *`` key as an argument, but ``ppname`` type can no longer be used there:: + + ppname key; + ppdict_get_something(dict, key); // wrong + ppdict_get_something(dict, key.data); // ok + + ppname *pkey; + ppdict_get_something(dict, (const char *)pkey); // wrong + ppdict_get_something(dict, pkey->data); // ok + +Consequently, functions / macros that used pointer to ``ppname`` (``ppdict_first()`` / ``ppdict_next()``), +now needs ``ppname **pname``. + +Cleanups +-------- + +Some of unused utils were removed. There is still some code in utils part that is not used by the library, +but I need this tollbox in many other places and don't want to maintain two versions. + +Some unification in integer types; ``size_t`` seems to be the best choice for and integer representing machine +word (``unsigned long`` is not long enough on windows), less utils dependencies, less compiler warnings. + diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/ajax-loader.gif b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/ajax-loader.gif new file mode 100644 index 00000000000..61faf8cab23 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/ajax-loader.gif differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/background_b01.png b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/background_b01.png new file mode 100644 index 00000000000..353f26dde08 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/background_b01.png differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/basic.css b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/basic.css new file mode 100644 index 00000000000..0807176ec0c --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/basic.css @@ -0,0 +1,676 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist td { + vertical-align: top; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: relative; + left: 0px; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.css b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.css new file mode 100644 index 00000000000..0464a74e637 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.css @@ -0,0 +1,490 @@ +/* + * bizstyle.css_t + * ~~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- business style theme. + * + * :copyright: Copyright 2011-2014 by Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', + 'Verdana', sans-serif; + font-size: 14px; + letter-spacing: -0.01em; + line-height: 150%; + text-align: center; + background-color: white; + background-image: url(background_b01.png); + color: black; + padding: 0; + border-right: 1px solid #336699; + border-left: 1px solid #336699; + + margin: 0px 40px 0px 40px; +} + +div.document { + background-color: white; + text-align: left; + background-repeat: repeat-x; + + -moz-box-shadow: 2px 2px 5px #000; + -webkit-box-shadow: 2px 2px 5px #000; +} + +div.bodywrapper { + margin: 0 0 0 240px; + border-left: 1px solid #ccc; +} + +div.body { + margin: 0; + padding: 0.5em 20px 20px 20px; +} + +div.related { + font-size: 1em; + + -moz-box-shadow: 2px 2px 5px #000; + -webkit-box-shadow: 2px 2px 5px #000; +} + +div.related ul { + background-color: #336699; + height: 100%; + overflow: hidden; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} + +div.related ul li { + color: white; + margin: 0; + padding: 0; + height: 2em; + float: left; +} + +div.related ul li.right { + float: right; + margin-right: 5px; +} + +div.related ul li a { + margin: 0; + padding: 0 5px 0 5px; + line-height: 1.75em; + color: #fff; +} + +div.related ul li a:hover { + color: #fff; + text-decoration: underline; +} + +div.sphinxsidebarwrapper { + padding: 0; +} + +div.sphinxsidebar { + margin: 0; + padding: 0.5em 12px 12px 12px; + width: 210px; + font-size: 1em; + text-align: left; +} + +div.sphinxsidebar h3, div.sphinxsidebar h4 { + margin: 1em 0 0.5em 0; + font-size: 1em; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border: 1px solid #336699; + background-color: #336699; +} + +div.sphinxsidebar h3 a { + color: white; +} + +div.sphinxsidebar ul { + padding-left: 1.5em; + margin-top: 7px; + padding: 0; + line-height: 130%; +} + +div.sphinxsidebar ul ul { + margin-left: 20px; +} + +div.sphinxsidebar input { + border: 1px solid #336699; +} + +div.footer { + background-color: white; + color: #336699; + padding: 3px 8px 3px 0; + clear: both; + font-size: 0.8em; + text-align: right; + border-bottom: 1px solid #336699; + + -moz-box-shadow: 2px 2px 5px #000; + -webkit-box-shadow: 2px 2px 5px #000; +} + +div.footer a { + color: #336699; + text-decoration: underline; +} + +/* -- body styles ----------------------------------------------------------- */ + +p { + margin: 0.8em 0 0.5em 0; +} + +a { + color: #336699; + text-decoration: none; +} + +a:hover { + color: #336699; + text-decoration: underline; +} + +div.body a { + text-decoration: underline; +} + +h1, h2, h3 { + color: #336699; +} + +h1 { + margin: 0; + padding: 0.7em 0 0.3em 0; + font-size: 1.5em; +} + +h2 { + margin: 1.3em 0 0.2em 0; + font-size: 1.35em; + padding-bottom: .5em; + border-bottom: 1px solid #336699; +} + +h3 { + margin: 1em 0 -0.3em 0; + font-size: 1.2em; + padding-bottom: .3em; + border-bottom: 1px solid #CCCCCC; +} + +div.body h1 a, div.body h2 a, div.body h3 a, +div.body h4 a, div.body h5 a, div.body h6 a { + color: black!important; +} + +h1 a.anchor, h2 a.anchor, h3 a.anchor, +h4 a.anchor, h5 a.anchor, h6 a.anchor { + display: none; + margin: 0 0 0 0.3em; + padding: 0 0.2em 0 0.2em; + color: #aaa!important; +} + +h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, +h5:hover a.anchor, h6:hover a.anchor { + display: inline; +} + +h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, +h5 a.anchor:hover, h6 a.anchor:hover { + color: #777; + background-color: #eee; +} + +a.headerlink { + color: #c60f0f!important; + font-size: 1em; + margin-left: 6px; + padding: 0 4px 0 4px; + text-decoration: none!important; +} + +a.headerlink:hover { + background-color: #ccc; + color: white!important; +} + +cite, code, tt { + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + letter-spacing: 0.01em; +} + +code { + background-color: #F2F2F2; + border-bottom: 1px solid #ddd; + color: #333; +} + +code.descname, code.descclassname, code.xref { + border: 0; +} + +hr { + border: 1px solid #abc; + margin: 2em; +} + +a code { + border: 0; + color: #CA7900; +} + +a code:hover { + color: #2491CF; +} + +pre { + background-color: transparent !important; + font-family: 'Consolas', 'Deja Vu Sans Mono', + 'Bitstream Vera Sans Mono', monospace; + font-size: 0.95em; + letter-spacing: 0.015em; + line-height: 120%; + padding: 0.5em; + border-right: 5px solid #ccc; + border-left: 5px solid #ccc; +} + +pre a { + color: inherit; + text-decoration: underline; +} + +td.linenos pre { + padding: 0.5em 0; +} + +div.quotebar { + background-color: #f8f8f8; + max-width: 250px; + float: right; + padding: 2px 7px; + border: 1px solid #ccc; +} + +div.topic { + background-color: #f8f8f8; +} + +table { + border-collapse: collapse; + margin: 0 -0.5em 0 -0.5em; +} + +table td, table th { + padding: 0.2em 0.5em 0.2em 0.5em; +} + +div.admonition { + font-size: 0.9em; + margin: 1em 0 1em 0; + border: 3px solid #cccccc; + background-color: #f7f7f7; + padding: 0; +} + +div.admonition p { + margin: 0.5em 1em 0.5em 1em; + padding: 0; +} + +div.admonition li p { + margin-left: 0; +} + +div.admonition pre, div.warning pre { + margin: 0; +} + +div.highlight { + margin: 0.4em 1em; +} + +div.admonition p.admonition-title { + margin: 0; + padding: 0.1em 0 0.1em 0.5em; + color: white; + border-bottom: 3px solid #cccccc; + font-weight: bold; + background-color: #165e83; +} + +div.danger { border: 3px solid #f0908d; background-color: #f0cfa0; } +div.error { border: 3px solid #f0908d; background-color: #ede4cd; } +div.warning { border: 3px solid #f8b862; background-color: #f0cfa0; } +div.caution { border: 3px solid #f8b862; background-color: #ede4cd; } +div.attention { border: 3px solid #f8b862; background-color: #f3f3f3; } +div.important { border: 3px solid #f0cfa0; background-color: #ede4cd; } +div.note { border: 3px solid #f0cfa0; background-color: #f3f3f3; } +div.hint { border: 3px solid #bed2c3; background-color: #f3f3f3; } +div.tip { border: 3px solid #bed2c3; background-color: #f3f3f3; } + +div.danger p.admonition-title, div.error p.admonition-title { + background-color: #b7282e; + border-bottom: 3px solid #f0908d; +} + +div.caution p.admonition-title, +div.warning p.admonition-title, +div.attention p.admonition-title { + background-color: #f19072; + border-bottom: 3px solid #f8b862; +} + +div.note p.admonition-title, div.important p.admonition-title { + background-color: #f8b862; + border-bottom: 3px solid #f0cfa0; +} + +div.hint p.admonition-title, div.tip p.admonition-title { + background-color: #7ebea5; + border-bottom: 3px solid #bed2c3; +} + +div.admonition ul, div.admonition ol, +div.warning ul, div.warning ol { + margin: 0.1em 0.5em 0.5em 3em; + padding: 0; +} + +div.versioninfo { + margin: 1em 0 0 0; + border: 1px solid #ccc; + background-color: #DDEAF0; + padding: 8px; + line-height: 1.3em; + font-size: 0.9em; +} + +.viewcode-back { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', + 'Verdana', sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} + +p.versionchanged span.versionmodified { + font-size: 0.9em; + margin-right: 0.2em; + padding: 0.1em; + background-color: #DCE6A0; +} + +/* -- table styles ---------------------------------------------------------- */ + +table.docutils { + margin: 1em 0; + padding: 0; + border: 1px solid white; + background-color: #f7f7f7; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 1px solid white; + border-bottom: 1px solid white; +} + +table.docutils td p { + margin-top: 0; + margin-bottom: 0.3em; +} + +table.field-list td, table.field-list th { + border: 0 !important; + word-break: break-word; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + color: white; + text-align: left; + padding-right: 5px; + background-color: #82A0BE; +} + +div.literal-block-wrapper div.code-block-caption { + background-color: #EEE; + border-style: solid; + border-color: #CCC; + border-width: 1px 5px; +} + +/* WIDE DESKTOP STYLE */ +@media only screen and (min-width: 1176px) { +body { + margin: 0 40px 0 40px; +} +} + +/* TABLET STYLE */ +@media only screen and (min-width: 768px) and (max-width: 991px) { +body { + margin: 0 40px 0 40px; +} +} + +/* MOBILE LAYOUT (PORTRAIT/320px) */ +@media only screen and (max-width: 767px) { +body { + margin: 0; +} +div.bodywrapper { + margin: 0; + width: 100%; + border: none; +} +div.sphinxsidebar { + display: none; +} +} + +/* MOBILE LAYOUT (LANDSCAPE/480px) */ +@media only screen and (min-width: 480px) and (max-width: 767px) { +body { + margin: 0 20px 0 20px; +} +} + +/* RETINA OVERRIDES */ +@media +only screen and (-webkit-min-device-pixel-ratio: 2), +only screen and (min-device-pixel-ratio: 2) { +} + +/* -- end ------------------------------------------------------------------- */ \ No newline at end of file diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.js b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.js new file mode 100644 index 00000000000..6614fe388d1 --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/bizstyle.js @@ -0,0 +1,41 @@ +// +// bizstyle.js +// ~~~~~~~~~~~ +// +// Sphinx javascript -- for bizstyle theme. +// +// This theme was created by referring to 'sphinxdoc' +// +// :copyright: Copyright 2012-2014 by Sphinx team, see AUTHORS. +// :license: BSD, see LICENSE for details. +// +$(document).ready(function(){ + if (navigator.userAgent.indexOf('iPhone') > 0 || + navigator.userAgent.indexOf('Android') > 0) { + $("li.nav-item-0 a").text("Top"); + } + + $("div.related:first ul li:not(.right) a").slice(1).each(function(i, item){ + if (item.text.length > 20) { + var tmpstr = item.text + $(item).attr("title", tmpstr); + $(item).text(tmpstr.substr(0, 17) + "..."); + } + }); + $("div.related:last ul li:not(.right) a").slice(1).each(function(i, item){ + if (item.text.length > 20) { + var tmpstr = item.text + $(item).attr("title", tmpstr); + $(item).text(tmpstr.substr(0, 17) + "..."); + } + }); +}); + +$(window).resize(function(){ + if ($(window).width() <= 776) { + $("li.nav-item-0 a").text("Top"); + } + else { + $("li.nav-item-0 a").text("pplib 0.1 documentation"); + } +}); \ No newline at end of file diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-bright.png b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-bright.png new file mode 100644 index 00000000000..15e27edb12a Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-bright.png differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-close.png b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-close.png new file mode 100644 index 00000000000..4d91bcf57de Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment-close.png differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment.png b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment.png new file mode 100644 index 00000000000..dfbc0cbd512 Binary files /dev/null and b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/comment.png differ diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries.js b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries.js new file mode 100644 index 00000000000..59735f59dcb --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries.js @@ -0,0 +1 @@ +if(typeof Object.create!=="function"){Object.create=function(e){function t(){}t.prototype=e;return new t}}var ua={toString:function(){return navigator.userAgent},test:function(e){return this.toString().toLowerCase().indexOf(e.toLowerCase())>-1}};ua.version=(ua.toString().toLowerCase().match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1];ua.webkit=ua.test("webkit");ua.gecko=ua.test("gecko")&&!ua.webkit;ua.opera=ua.test("opera");ua.ie=ua.test("msie")&&!ua.opera;ua.ie6=ua.ie&&document.compatMode&&typeof document.documentElement.style.maxHeight==="undefined";ua.ie7=ua.ie&&document.documentElement&&typeof document.documentElement.style.maxHeight!=="undefined"&&typeof XDomainRequest==="undefined";ua.ie8=ua.ie&&typeof XDomainRequest!=="undefined";var domReady=function(){var e=[];var t=function(){if(!arguments.callee.done){arguments.callee.done=true;for(var t=0;t=200&&r.status<300||r.status===304||navigator.userAgent.indexOf("Safari")>-1&&typeof r.status==="undefined"){t(r.responseText)}else{n()}document.documentElement.style.cursor="";r=null}};r.send("")};var l=function(t){t=t.replace(e.REDUNDANT_COMPONENTS,"");t=t.replace(e.REDUNDANT_WHITESPACE,"$1");t=t.replace(e.WHITESPACE_IN_PARENTHESES,"($1)");t=t.replace(e.MORE_WHITESPACE," ");t=t.replace(e.FINAL_SEMICOLONS,"}");return t};var c={stylesheet:function(t){var n={};var r=[],i=[],s=[],o=[];var u=t.cssHelperText;var a=t.getAttribute("media");if(a){var f=a.toLowerCase().split(",")}else{var f=["all"]}for(var l=0;l-1&&a.href&&a.href.length!==0&&!a.disabled){r[r.length]=a}}if(r.length>0){var c=0;var d=function(){c++;if(c===r.length){i()}};var v=function(t){var n=t.href;f(n,function(r){r=l(r).replace(e.RELATIVE_URLS,"url("+n.substring(0,n.lastIndexOf("/"))+"/$1)");t.cssHelperText=r;d()},d)};for(u=0;u0){r.setAttribute("media",t.join(","))}document.getElementsByTagName("head")[0].appendChild(r);if(r.styleSheet){r.styleSheet.cssText=e}else{r.appendChild(document.createTextNode(e))}r.addedWithCssHelper=true;if(typeof n==="undefined"||n===true){cssHelper.parsed(function(t){var n=p(r,e);for(var i in n){if(n.hasOwnProperty(i)){g(i,n[i])}}a("newStyleParsed",r)})}else{r.parsingDisallowed=true}return r},removeStyle:function(e){return e.parentNode.removeChild(e)},parsed:function(e){if(n){s(e)}else{if(typeof t!=="undefined"){if(typeof e==="function"){e(t)}}else{s(e);d()}}},stylesheets:function(e){cssHelper.parsed(function(t){e(m.stylesheets||y("stylesheets"))})},mediaQueryLists:function(e){cssHelper.parsed(function(t){e(m.mediaQueryLists||y("mediaQueryLists"))})},rules:function(e){cssHelper.parsed(function(t){e(m.rules||y("rules"))})},selectors:function(e){cssHelper.parsed(function(t){e(m.selectors||y("selectors"))})},declarations:function(e){cssHelper.parsed(function(t){e(m.declarations||y("declarations"))})},properties:function(e){cssHelper.parsed(function(t){e(m.properties||y("properties"))})},broadcast:a,addListener:function(e,t){if(typeof t==="function"){if(!u[e]){u[e]={listeners:[]}}u[e].listeners[u[e].listeners.length]=t}},removeListener:function(e,t){if(typeof t==="function"&&u[e]){var n=u[e].listeners;for(var r=0;r=a||s&&l0}}else if("device-height"===e.substring(r-13,r)){c=screen.height;if(t!==null){if(u==="length"){return i&&c>=a||s&&c0}}else if("width"===e.substring(r-5,r)){l=document.documentElement.clientWidth||document.body.clientWidth;if(t!==null){if(u==="length"){return i&&l>=a||s&&l0}}else if("height"===e.substring(r-6,r)){c=document.documentElement.clientHeight||document.body.clientHeight;if(t!==null){if(u==="length"){return i&&c>=a||s&&c0}}else if("device-aspect-ratio"===e.substring(r-19,r)){return u==="aspect-ratio"&&screen.width*a[1]===screen.height*a[0]}else if("color-index"===e.substring(r-11,r)){var h=Math.pow(2,screen.colorDepth);if(t!==null){if(u==="absolute"){return i&&h>=a||s&&h0}}else if("color"===e.substring(r-5,r)){var p=screen.colorDepth;if(t!==null){if(u==="absolute"){return i&&p>=a||s&&p0}}else if("resolution"===e.substring(r-10,r)){var d;if(f==="dpcm"){d=o("1cm")}else{d=o("1in")}if(t!==null){if(u==="resolution"){return i&&d>=a||s&&d0}}else{return false}};var a=function(e){var t=e.getValid();var n=e.getExpressions();var r=n.length;if(r>0){for(var i=0;i0){u=false;for(var f=0;f0){l[c++]=","}l[c++]=h}}if(l.length>0){r[r.length]=cssHelper.addStyle("@media "+l.join("")+"{"+e.getCssText()+"}",t,false)}};var l=function(e,t){for(var n=0;n0}}var o=[],u=[];for(var f in i){if(i.hasOwnProperty(f)){o[o.length]=f;if(i[f]){u[u.length]=f}if(f==="all"){n=true}}}if(u.length>0){r[r.length]=cssHelper.addStyle(e.getCssText(),u,false)}var c=e.getMediaQueryLists();if(n){l(c)}else{l(c,o)}};var h=function(e){for(var t=0;td||Math.abs(s-t)>d){e=n;t=s;clearTimeout(r);r=setTimeout(function(){if(!i()){p()}else{cssHelper.broadcast("cssMediaQueriesTested")}},500)}};window.onresize=function(){var e=window.onresize||function(){};return function(){e();s()}}()};var m=document.documentElement;m.style.marginLeft="-32767px";setTimeout(function(){m.style.marginLeft=""},5e3);return function(){if(!i()){cssHelper.addListener("newStyleParsed",function(e){c(e.cssHelperParsed.stylesheet)});cssHelper.addListener("cssMediaQueriesTested",function(){if(ua.ie){m.style.width="1px"}setTimeout(function(){m.style.width="";m.style.marginLeft=""},0);cssHelper.removeListener("cssMediaQueriesTested",arguments.callee)});s();p()}else{m.style.marginLeft=""}v()}}());try{document.execCommand("BackgroundImageCache",false,true)}catch(e){} diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries_src.js b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries_src.js new file mode 100644 index 00000000000..f21dd4949aa --- /dev/null +++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_static/css3-mediaqueries_src.js @@ -0,0 +1,1104 @@ +/* +css3-mediaqueries.js - CSS Helper and CSS3 Media Queries Enabler + +author: Wouter van der Graaf +version: 1.0 (20110330) +license: MIT +website: http://code.google.com/p/css3-mediaqueries-js/ + +W3C spec: http://www.w3.org/TR/css3-mediaqueries/ + +Note: use of embedded