From 6a71264a6130cdaade21807b71c1c2e80d060f69 Mon Sep 17 00:00:00 2001 From: Hanspeter Portner Date: Sat, 2 Jan 2021 17:47:40 +0100 Subject: [PATCH] Squashed 'pugl/' changes from 1b1a1c3a..0a23647a 0a23647a Add support for any mime type in X11 clipboard a92a194b Fix flaky build on Windows c186b1e8 Require Python3 to build documentation 47685df9 Fix Vulkan C++ bindings on Windows f829cfa6 Make demo programs work from any directory, and install them 07c8253c Print an error message in Vulkan demo when shaders are not found 2f48c3e6 Fix a conversion warning with MinGW 3d864fcd Add clipboard test e0b78036 Enable test coverage in debug builds 9cb91cde Make puglShow() realize automatically on Windows and MacOS 8f5d0ac9 Build documentation on CI 503ba93a Generate documentation with Sphinx caf3f4fc Update autowaf 60d0de60 Use named groups to group documentation c10c2a11 Remove top-level documentation group 5c651ee2 Add missing documentation for pugl::Event fields ceafc915 Document PUGL_CHECK_CONSTRUCTION a9922aa5 Use consistent spelling in documentation 81fd21da Remove file documentation 9de33a88 Don't use lists in return documentation c29aaaf6 Add pugl::World constructor overload that takes a flag ee6aebaf Remove stub event handlers from pugl::View 2d90c04e Simplify and minify icon SVG adc92518 Rename puglShowWindow and puglHideWindow to puglShow an puglHide 7ce9b578 Move puglEnterContext and puglLeaveContext to GL backends 3e9a2e01 Pass vkGetInstanceProcAddr to puglCreateSurface instead of a loader 6426b034 Suppress various clang-tidy warnings 0a5b734f X11: Fix position of child windows and clean up window creation code c7213092 Fix asan errors on X11 7dde3e3a Add missing return 6a8da097 Cleanup: Fix typo f0f058db Run clang-tidy on all headers and fix various issues 71a9fbf2 Make event handling in C++ more flexible 92edbddd Reorder methods in C++ bindings to match C header groups b62c1874 Add missing documentation for Vulkan f7cce780 Use static polymorphism in C++ bindings 71312135 Make use of exceptions optional 745bc88b Make most methods noexcept 416f0c25 Remove use of cassert and type_traits 5676ec17 Use a custom exception type for failed construction 5d7ddd8c Remove pugl::Clock af3d564e Remove use of std::unique_ptr 31e144e6 Cleanup: Remove unnecessary include acdcfb58 Cleanup: Remove unnecessary namespace qualifications 5ee68d83 Fix Cairo build on Mac and Windows f9923d7b Remove logging API caf17373 Clean up installed man pages d7703c82 Simplify header names 09fd1190 Remove GL and GLU wrapper headers d3d0c558 Make C++ bindings a separate package 750eb802 Move C++ bindings to a separate directory 21d1e350 Move implementation source files to a conventional src directory 4ae4dd5b Add Vulkan demos 1bcc437a Add Vulkan backends 472d42f2 Add missing include fd8743c7 Don't send expose events when window is minimized 612aae51 Replace live resize with loop events 9c2f1888 Remove unused Doxygen configuration keys a8291ce0 Fix documentation typo 66cec5bb Use single-line doc comments where possible eadf8e9a Resurrect puglEnterContext() and puglLeaveContext() 336ab6bc Add noexcept annotations to C++ Wrapper base class 244a0a5b Add timer methods to C++ wrapper 4535f74f Make backend function wrappers noexcept c6be2e43 Fix shader demo arguments to allow running at maximum framerate 01888707 Check all implementation files with IWYU 88e23c4a Simplify documentation structure 361b09bc Simplify documentation style c15b5da4 Fix outdated function reference in Cairo documentation f88687a9 Cleanup: Always put return types on their own line 77fccc3e Cleanup: Sort includes 641a4842 Cleanup: Use conventional style for ObjC methods 95beec3f Cleanup: Use consistent style for preprocessor conditionals 74a2b237 Fix clang-tidy issues in Windows code d678291f Fix building with clang on Windows 968289f7 Add no-cxx configure option 4857f9b7 Fix Cairo backend compilation on Windows 72b11f22 Use separate clang-tidy configurations in different directories feb6c4f7 Add missing include guards 063ddc8d Add missing includes 380edd6d Move includes to a separate directory e78e00a4 Check pugl.hpp and pugl.ipp with IWYU a385c3cb Cleanup: Reformat pugl.hpp and pugl.ipp 0020f0df Improve return code documentation 31245d35 Fix puglSendEvent() error handling on X11 a8d2aa27 Fix puglSetFrame() error handling on X11 83c4baa2 Split stub backends into separate files a8739542 Gracefully handle puglRealize() being called twice f2e294f9 Cleanup: Fix IWYU warnings c5ca8a3c Cleanup: Fix redundancy in test lists 5d26c74f Cleanup: Fix long line db0a48e7 Windows: Use default cursor on window decoration 743db997 Mac: React to cursorUpdate cdf10456 Update autowaf 879e876b Windows: Fix cursor when leaving client area f86e7d57 Windows: Return backend errors directly 4ee94da4 Set a default size in pugl_print_events 418a24f8 Show errors in example programs consistently d10bd6cc Only build header warning test in strict mode 06c0bc8a Add const attribute to backend accessors 5f8eca21 Use unsigned constants in enum definitions e552cb32 Suppress fewer MSVC warnings in header test d981ba92 Suppress IWYU warnings in build tests c918e02f Suppress MSVC warnings in header compile test 96f6df5b Explicitly declare all special methods 24949b82 Move cube vertex data to the file where it is actually used 4531da00 Fix potentially short string buffer 885eeb04 Suppress warnings in release builds 43345a03 Update autowaf fab3bc30 Use refresh rate to better drive example event loop 0b876c3d Add refresh rate hint a36408b7 Print all view hints in shader demo and hint tests cc5c38b1 Add puglGetViewHint() 6ca124d3 Set defaults to 32-bit RGBA with no depth or stencil buffer 72f019e7 Store real double buffer value in hint and remove separate variable 630f0a38 Refuse to set hints to PUGL_DONT_CARE when it doesn't make sense 3da72032 Change FPS print format in demos for consistency with other output 95703acf Fix library names in pkg-config files git-subtree-dir: pugl git-subtree-split: 0a23647a550f50820800e6db39bc36027adef339 --- .clang-format | 2 +- .clang-tidy | 19 +- .gitlab-ci.yml | 9 +- AUTHORS | 1 + README.md | 52 +- bindings/cxx/include/.clang-tidy | 14 + .../cxx/include/pugl/cairo.hpp | 17 +- .../cxx/include/pugl/gl.hpp | 36 +- {pugl => bindings/cxx/include/pugl}/pugl.hpp | 513 ++-- .../cxx/include/pugl/stub.hpp | 17 +- bindings/cxx/include/pugl/vulkan.hpp | 168 ++ doc/_static/custom.css | 95 + doc/_templates/about.html | 57 + doc/c/Doxyfile | 30 + doc/c/index.rst | 6 + doc/c/overview.rst | 579 ++++ doc/c/reference.rst | 18 + doc/c/wscript | 43 + doc/conf.py.in | 88 + doc/cpp/Doxyfile | 40 + doc/cpp/c-reference.rst | 20 + doc/cpp/cpp-reference.rst | 18 + doc/cpp/index.rst | 7 + doc/cpp/overview.rst | 423 +++ doc/cpp/wscript | 44 + doc/deployment.rst | 23 + doc/footer.html | 20 - doc/header.html | 49 - doc/layout.xml | 194 -- doc/mainpage.md | 42 +- doc/pugl.rst | 26 + doc/reference.doxygen.in | 2462 ----------------- doc/style.css | 863 ------ examples/.clang-tidy | 38 + examples/cube_view.h | 54 + examples/demo_utils.h | 61 +- examples/file_utils.c | 68 + pugl/gl.h => examples/file_utils.h | 33 +- examples/glad/glad.h | 2 - examples/pugl_cairo_demo.c | 9 +- examples/pugl_cursor_demo.c | 11 +- examples/pugl_cxx_demo.cpp | 41 +- examples/pugl_embed_demo.c | 10 +- examples/pugl_print_events.c | 15 +- examples/pugl_shader_demo.c | 116 +- examples/pugl_vulkan_cxx_demo.cpp | 1871 +++++++++++++ examples/pugl_vulkan_demo.c | 1139 ++++++++ examples/pugl_window_demo.c | 9 +- examples/rects.h | 11 +- examples/shader_utils.h | 5 + {shaders => examples/shaders}/header_330.glsl | 0 {shaders => examples/shaders}/header_420.glsl | 0 {shaders => examples/shaders}/rect.frag | 0 {shaders => examples/shaders}/rect.vert | 0 examples/sybok.hpp | 2358 ++++++++++++++++ include/.clang-tidy | 9 + pugl/pugl_cairo.h => include/pugl/cairo.h | 17 +- pugl/pugl_gl.h => include/pugl/gl.h | 64 +- {pugl => include/pugl}/pugl.h | 373 ++- pugl/pugl_stub.h => include/pugl/stub.h | 27 +- include/pugl/vulkan.h | 146 + pugl.pc.in | 2 +- pugl/glu.h | 32 - pugl/pugl.ipp | 154 -- resources/pugl.svg | 92 +- scripts/dox_to_sphinx.py | 666 +++++ src/.clang-tidy | 19 + {pugl/detail => src}/implementation.c | 118 +- {pugl/detail => src}/implementation.h | 39 +- {pugl/detail => src}/mac.h | 14 +- {pugl/detail => src}/mac.m | 201 +- {pugl/detail => src}/mac_cairo.m | 21 +- {pugl/detail => src}/mac_gl.m | 63 +- {pugl/detail => src}/mac_stub.m | 16 +- src/mac_vulkan.m | 213 ++ {pugl/detail => src}/stub.h | 5 - {pugl/detail => src}/types.h | 10 +- {pugl/detail => src}/win.c | 155 +- {pugl/detail => src}/win.h | 37 +- {pugl/detail => src}/win_cairo.c | 17 +- {pugl/detail => src}/win_gl.c | 46 +- src/win_stub.c | 80 + src/win_vulkan.c | 127 + {pugl/detail => src}/x11.c | 267 +- {pugl/detail => src}/x11.h | 23 +- {pugl/detail => src}/x11_cairo.c | 10 +- {pugl/detail => src}/x11_gl.c | 73 +- src/x11_stub.c | 58 + src/x11_vulkan.c | 131 + test/.clang-tidy | 14 + test/test_build.c | 10 +- test/test_build.cpp | 13 +- test/test_clipboard.c | 104 + test/test_gl_hints.c | 89 + test/test_realize.c | 100 + test/test_redisplay.c | 4 +- test/test_show_hide.c | 6 +- test/test_stub_hints.c | 80 + test/test_timer.c | 4 +- test/test_update.c | 4 +- test/test_utils.h | 70 +- waflib | 2 +- wscript | 403 ++- 103 files changed, 10800 insertions(+), 5274 deletions(-) create mode 100644 bindings/cxx/include/.clang-tidy rename pugl/pugl_cairo.hpp => bindings/cxx/include/pugl/cairo.hpp (80%) rename pugl/pugl_gl.hpp => bindings/cxx/include/pugl/gl.hpp (69%) rename {pugl => bindings/cxx/include/pugl}/pugl.hpp (55%) rename pugl/pugl_stub.hpp => bindings/cxx/include/pugl/stub.hpp (80%) create mode 100644 bindings/cxx/include/pugl/vulkan.hpp create mode 100644 doc/_static/custom.css create mode 100644 doc/_templates/about.html create mode 100644 doc/c/Doxyfile create mode 100644 doc/c/index.rst create mode 100644 doc/c/overview.rst create mode 100644 doc/c/reference.rst create mode 100644 doc/c/wscript create mode 100644 doc/conf.py.in create mode 100644 doc/cpp/Doxyfile create mode 100644 doc/cpp/c-reference.rst create mode 100644 doc/cpp/cpp-reference.rst create mode 100644 doc/cpp/index.rst create mode 100644 doc/cpp/overview.rst create mode 100644 doc/cpp/wscript create mode 100644 doc/deployment.rst delete mode 100644 doc/footer.html delete mode 100644 doc/header.html delete mode 100644 doc/layout.xml create mode 100644 doc/pugl.rst delete mode 100644 doc/reference.doxygen.in delete mode 100644 doc/style.css create mode 100644 examples/.clang-tidy create mode 100644 examples/file_utils.c rename pugl/gl.h => examples/file_utils.h (54%) create mode 100644 examples/pugl_vulkan_cxx_demo.cpp create mode 100644 examples/pugl_vulkan_demo.c rename {shaders => examples/shaders}/header_330.glsl (100%) rename {shaders => examples/shaders}/header_420.glsl (100%) rename {shaders => examples/shaders}/rect.frag (100%) rename {shaders => examples/shaders}/rect.vert (100%) create mode 100644 examples/sybok.hpp create mode 100644 include/.clang-tidy rename pugl/pugl_cairo.h => include/pugl/cairo.h (77%) rename pugl/pugl_gl.h => include/pugl/gl.h (50%) rename {pugl => include/pugl}/pugl.h (88%) rename pugl/pugl_stub.h => include/pugl/stub.h (64%) create mode 100644 include/pugl/vulkan.h delete mode 100644 pugl/glu.h delete mode 100644 pugl/pugl.ipp create mode 100755 scripts/dox_to_sphinx.py create mode 100644 src/.clang-tidy rename {pugl/detail => src}/implementation.c (84%) rename {pugl/detail => src}/implementation.h (73%) rename {pugl/detail => src}/mac.h (88%) rename {pugl/detail => src}/mac.m (89%) rename {pugl/detail => src}/mac_cairo.m (91%) rename {pugl/detail => src}/mac_gl.m (73%) rename {pugl/detail => src}/mac_stub.m (89%) create mode 100644 src/mac_vulkan.m rename {pugl/detail => src}/stub.h (95%) rename {pugl/detail => src}/types.h (95%) rename {pugl/detail => src}/win.c (90%) rename {pugl/detail => src}/win.h (85%) rename {pugl/detail => src}/win_cairo.c (92%) rename {pugl/detail => src}/win_gl.c (90%) create mode 100644 src/win_stub.c create mode 100644 src/win_vulkan.c rename {pugl/detail => src}/x11.c (85%) rename {pugl/detail => src}/x11.h (81%) rename {pugl/detail => src}/x11_cairo.c (96%) rename {pugl/detail => src}/x11_gl.c (80%) create mode 100644 src/x11_stub.c create mode 100644 src/x11_vulkan.c create mode 100644 test/.clang-tidy create mode 100644 test/test_clipboard.c create mode 100644 test/test_gl_hints.c create mode 100644 test/test_realize.c create mode 100644 test/test_stub_hints.c diff --git a/.clang-format b/.clang-format index 043fd1f..a505e26 100644 --- a/.clang-format +++ b/.clang-format @@ -33,7 +33,7 @@ BraceWrapping: AfterObjCDeclaration: true AfterStruct: false AfterUnion: false - AfterExternBlock: true + AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false diff --git a/.clang-tidy b/.clang-tidy index c8039e1..1e40901 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,21 +1,4 @@ Checks: > *, - -*avoid-c-arrays, - -*magic-numbers, - -*uppercase-literal-suffix, - -android-cloexec-fopen, - -bugprone-suspicious-string-compare, - -cert-flp30-c, - -clang-analyzer-alpha.*, - -clang-analyzer-security.FloatLoopCounter, - -google-runtime-references, - -hicpp-multiway-paths-covered, - -hicpp-signed-bitwise, - -llvm-header-guard, - -modernize-use-trailing-return-type, - -readability-else-after-return, - -readability-implicit-bool-conversion, - -readability-named-parameter, -WarningsAsErrors: '' -HeaderFilterRegex: 'pugl/.*|test/.*|examples/.*' FormatStyle: file +WarningsAsErrors: '*' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 42d14cd..c0d0330 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,7 +43,7 @@ arm64_rel: x64_dbg: <<: *build_definition image: lv2plugin/debian-x64 - script: python ./waf configure build -dST --werror --no-coverage --docs + script: python3 ./waf configure build -dST --werror --no-coverage --docs artifacts: paths: - build/doc @@ -108,7 +108,12 @@ win_rel: pages: stage: deploy - script: mv build/doc/html/ public/ + script: + - mkdir public + - mkdir public/c + - mkdir public/cpp + - mv build/doc/c/singlehtml/ public/c/singlehtml/ + - mv build/doc/cpp/singlehtml/ public/cpp/singlehtml/ dependencies: - x64_dbg artifacts: diff --git a/AUTHORS b/AUTHORS index 18aadaf..99f6dac 100644 --- a/AUTHORS +++ b/AUTHORS @@ -10,3 +10,4 @@ Jordan Halase Oliver Schmidt Zoƫ Sparks Jean Pierre Cimalando +Thomas Brand diff --git a/README.md b/README.md index e8794bc..97906a8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Pugl Pugl (PlUgin Graphics Library) is a minimal portable API for GUIs which is suitable for use in plugins. It works on X11, MacOS, and Windows, and -optionally supports OpenGL and Cairo graphics contexts. +optionally supports Vulkan, OpenGL, and Cairo graphics contexts. Pugl is vaguely similar to libraries like GLUT and GLFW, but with some distinguishing features: @@ -37,35 +37,16 @@ being, however, the API may break occasionally. Please report any relevant feedback, or file feature requests, so that we can ensure that the released API is stable for as long as possible. -Distribution ------------- - -Pugl is designed for flexible distribution. It can be used by simply including -the source code, or installed and linked against as a static or shared library. -Static linking or direct inclusion is a good idea for plugins that will be -distributed as binaries to avoid dependency problems. - -If you are including the code, please use a submodule so that suitable changes -can be merged upstream to keep fragmentation to a minimum. - -When installed, Pugl is split into different libraries to keep dependencies -minimal. The core implementation is separate from graphics backends: - - * The core implementation for a particular platform is in one library: - `pugl_x11`, `pugl_mac`, or `pugl_win`. This does not depend on backends or - their dependencies. +Documentation +------------- - * Backends for platforms are in separate libraries, which depend on the core: - `pugl_x11_cairo`, `pugl_x11_gl`, `pugl_mac_cairo`, and so on. +Pugl is a C library that includes C++ bindings. +Each API is documented separately: -Applications must link against the core and at least one backend. Normally, -this can be achieved by simply depending on the package `pugl-gl-0` or -`pugl-cairo-0`. Though it is possible to compile everything into a monolithic -library, distributions should retain this separation so that GL applications -don't depend on Cairo and its dependencies, or vice-versa. + * [C Documentation](https://lv2.gitlab.io/pugl/c/singlehtml) + * [C++ Documentation](https://lv2.gitlab.io/pugl/cpp/singlehtml) -Distributions are encouraged to include static libraries if possible so that -developers can build portable plugin binaries. +The documentation can also be built from the source by configuring with `--docs`. Testing ------- @@ -81,8 +62,8 @@ Then, after building, the unit tests can be run: ./waf ./waf test --gui-tests -Several example programs are included that serve as both manual tests and -demonstrations: +The `examples` directory contains several programs that serve as both manual +tests and demonstrations: * `pugl_embed_demo` shows a view embedded in another, and also tests requesting attention (which happens after 5 seconds), keyboard focus @@ -104,15 +85,14 @@ demonstrations: * `pugl_cxx_demo` is a simple cube demo that uses the C++ API. + * `pugl_vulkan_demo` is a simple example of using Vulkan in C that simply + clears the window. + + * `pugl_vulkan_cxx_demo` is a more advanced Vulkan demo in C++ that draws many + animated rectangles like `pugl_shader_demo`. + All example programs support several command line options to control various behaviours, see the output of `--help` for details. Please file an issue if any of these programs do not work as expected on your system. -Documentation -------------- - -The [API reference](https://lv2.gitlab.io/pugl/) for the latest master is -available online, and can also be built from the source code by configuring -with `--docs`. - -- David Robillard diff --git a/bindings/cxx/include/.clang-tidy b/bindings/cxx/include/.clang-tidy new file mode 100644 index 0000000..816223d --- /dev/null +++ b/bindings/cxx/include/.clang-tidy @@ -0,0 +1,14 @@ +Checks: > + *, + -*-uppercase-literal-suffix, + -clang-diagnostic-unused-macros, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-static-cast-downcast, + -google-runtime-references, + -hicpp-named-parameter, + -llvmlibc-*, + -modernize-use-trailing-return-type, + -readability-implicit-bool-conversion, + -readability-named-parameter, +FormatStyle: file +HeaderFilterRegex: 'pugl/.*' diff --git a/pugl/pugl_cairo.hpp b/bindings/cxx/include/pugl/cairo.hpp similarity index 80% rename from pugl/pugl_cairo.hpp rename to bindings/cxx/include/pugl/cairo.hpp index 5b17ab7..7416589 100644 --- a/pugl/pugl_cairo.hpp +++ b/bindings/cxx/include/pugl/cairo.hpp @@ -14,16 +14,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/** - @file pugl_cairo.hpp - @brief Declaration of Cairo backend accessor for C++. -*/ - -#ifndef PUGL_PUGL_CAIRO_HPP -#define PUGL_PUGL_CAIRO_HPP +#ifndef PUGL_CAIRO_HPP +#define PUGL_CAIRO_HPP +#include "pugl/cairo.h" #include "pugl/pugl.h" -#include "pugl/pugl_cairo.h" namespace pugl { @@ -35,8 +30,8 @@ namespace pugl { */ /// @copydoc puglCairoBackend -static inline const PuglBackend* -cairoBackend() +inline const PuglBackend* +cairoBackend() noexcept { return puglCairoBackend(); } @@ -47,4 +42,4 @@ cairoBackend() } // namespace pugl -#endif // PUGL_PUGL_CAIRO_HPP +#endif // PUGL_CAIRO_HPP diff --git a/pugl/pugl_gl.hpp b/bindings/cxx/include/pugl/gl.hpp similarity index 69% rename from pugl/pugl_gl.hpp rename to bindings/cxx/include/pugl/gl.hpp index 4bc5bbd..d8459a8 100644 --- a/pugl/pugl_gl.hpp +++ b/bindings/cxx/include/pugl/gl.hpp @@ -14,16 +14,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/** - @file pugl_gl.hpp - @brief OpenGL-specific C++ API. -*/ - -#ifndef PUGL_PUGL_GL_HPP -#define PUGL_PUGL_GL_HPP +#ifndef PUGL_GL_HPP +#define PUGL_GL_HPP +#include "pugl/gl.h" #include "pugl/pugl.h" -#include "pugl/pugl_gl.h" +#include "pugl/pugl.hpp" namespace pugl { @@ -38,15 +34,29 @@ namespace pugl { using GlFunc = PuglGlFunc; /// @copydoc puglGetProcAddress -static inline GlFunc -getProcAddress(const char* name) +inline GlFunc +getProcAddress(const char* name) noexcept { return puglGetProcAddress(name); } +/// @copydoc puglEnterContext +inline Status +enterContext(View& view) noexcept +{ + return static_cast(puglEnterContext(view.cobj())); +} + +/// @copydoc puglLeaveContext +inline Status +leaveContext(View& view) noexcept +{ + return static_cast(puglLeaveContext(view.cobj())); +} + /// @copydoc puglGlBackend -static inline const PuglBackend* -glBackend() +inline const PuglBackend* +glBackend() noexcept { return puglGlBackend(); } @@ -57,4 +67,4 @@ glBackend() } // namespace pugl -#endif // PUGL_PUGL_GL_HPP +#endif // PUGL_GL_HPP diff --git a/pugl/pugl.hpp b/bindings/cxx/include/pugl/pugl.hpp similarity index 55% rename from pugl/pugl.hpp rename to bindings/cxx/include/pugl/pugl.hpp index 3072560..1a07734 100644 --- a/pugl/pugl.hpp +++ b/bindings/cxx/include/pugl/pugl.hpp @@ -14,35 +14,26 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/** - @file pugl.hpp - @brief Pugl C++ API wrapper. -*/ - #ifndef PUGL_PUGL_HPP #define PUGL_PUGL_HPP #include "pugl/pugl.h" -#include -#include -#include -#include -#include -#include +#include -/** - @defgroup pugl_cxx C++ API - C++ API wrapper. +#if defined(PUGL_HPP_THROW_FAILED_CONSTRUCTION) +# include +#elif defined(PUGL_HPP_ASSERT_CONSTRUCTION) +# include +#endif - @ingroup pugl - @{ -*/ +namespace pugl { /** - Pugl C++ API namespace. + @defgroup puglxx Pugl C++ API + Pugl C++ API wrapper. + @{ */ -namespace pugl { namespace detail { @@ -50,27 +41,39 @@ namespace detail { template using FreeFunc = void (*)(T*); -/// Simple overhead-free deleter for a C object -template Free> -struct Deleter { - void operator()(T* ptr) { Free(ptr); } -}; - /// Generic C++ wrapper for a C object template Free> class Wrapper { public: - T* cobj() { return _ptr.get(); } - const T* cobj() const { return _ptr.get(); } + Wrapper(const Wrapper&) = delete; + Wrapper& operator=(const Wrapper&) = delete; + + Wrapper(Wrapper&& wrapper) noexcept + : _ptr{wrapper._ptr} + { + wrapper._ptr = nullptr; + } + + Wrapper& operator=(Wrapper&& wrapper) noexcept + { + _ptr = wrapper._ptr; + wrapper._ptr = nullptr; + return *this; + } + + ~Wrapper() noexcept { Free(_ptr); } + + T* cobj() noexcept { return _ptr; } + const T* cobj() const noexcept { return _ptr; } protected: - explicit Wrapper(T* ptr) - : _ptr(ptr, Deleter{}) + explicit Wrapper(T* ptr) noexcept + : _ptr{ptr} {} private: - std::unique_ptr> _ptr; + T* _ptr; }; } // namespace detail @@ -79,8 +82,6 @@ using Rect = PuglRect; ///< @copydoc PuglRect /** @defgroup eventsxx Events - @ingroup pugl_cxx - @copydoc events @{ */ @@ -96,8 +97,10 @@ using Rect = PuglRect; ///< @copydoc PuglRect */ template struct Event final : Base { + /// The type of the corresponding C event structure using BaseEvent = Base; + /// The `type` field of the corresponding C event structure static constexpr const PuglEventType type = t; }; @@ -172,11 +175,15 @@ using ClientEvent = Event; /// @copydoc PuglEventTimer using TimerEvent = Event; +/// @copydoc PuglEventLoopEnter +using LoopEnterEvent = Event; + +/// @copydoc PuglEventLoopLeave +using LoopLeaveEvent = Event; + /** @} @defgroup statusxx Status - @ingroup pugl_cxx - @copydoc status @{ */ @@ -199,8 +206,8 @@ enum class Status { static_assert(Status(PUGL_UNSUPPORTED_TYPE) == Status::unsupportedType, ""); /// @copydoc puglStrerror -static inline const char* -strerror(const pugl::Status status) +inline const char* +strerror(const Status status) noexcept { return puglStrerror(static_cast(status)); } @@ -208,13 +215,9 @@ strerror(const pugl::Status status) /** @} @defgroup worldxx World - @ingroup pugl_cxx - @copydoc world @{ */ -class World; - /// @copydoc PuglWorldType enum class WorldType { program, ///< @copydoc PUGL_PROGRAM @@ -232,109 +235,97 @@ static_assert(WorldFlag(PUGL_WORLD_THREADS) == WorldFlag::threads, ""); using WorldFlags = PuglWorldFlags; ///< @copydoc PuglWorldFlags -/// @copydoc PuglLogLevel -enum class LogLevel { - err = PUGL_LOG_LEVEL_ERR, ///< @copydoc PUGL_LOG_LEVEL_ERR - warning = PUGL_LOG_LEVEL_WARNING, ///< @copydoc PUGL_LOG_LEVEL_WARNING - info = PUGL_LOG_LEVEL_INFO, ///< @copydoc PUGL_LOG_LEVEL_INFO - debug = PUGL_LOG_LEVEL_DEBUG, ///< @copydoc PUGL_LOG_LEVEL_DEBUG -}; +#if defined(PUGL_HPP_THROW_FAILED_CONSTRUCTION) -static_assert(LogLevel(PUGL_LOG_LEVEL_DEBUG) == LogLevel::debug, ""); - -/// @copydoc PuglLogFunc -using LogFunc = - std::function; - -/** - A `std::chrono` compatible clock that uses Pugl time. -*/ -class Clock +/// An exception thrown when construction fails +class FailedConstructionError : public std::exception { public: - using rep = double; ///< Time representation - using duration = std::chrono::duration; ///< Duration in seconds - using time_point = std::chrono::time_point; ///< A Pugl time point - - static constexpr bool is_steady = true; ///< Steady clock flag, always true - - /// Construct a clock that uses time from puglGetTime() - explicit Clock(World& world) - : _world{world} + FailedConstructionError(const char* const msg) noexcept + : _msg{msg} {} - /// Return the current time - time_point now() const; + virtual const char* what() const noexcept override; private: - const pugl::World& _world; + const char* _msg; }; +# define PUGL_CHECK_CONSTRUCTION(cond, msg) \ + do { \ + if (!(cond)) { \ + throw FailedConstructionError(msg); \ + } \ + } while (0) + +#elif defined(PUGL_HPP_ASSERT_CONSTRUCTION) +# define PUGL_CHECK_CONSTRUCTION(cond, msg) assert(cond); +#else +/** + Configurable macro for handling construction failure. + + If `PUGL_HPP_THROW_FAILED_CONSTRUCTION` is defined, then this throws a + `pugl::FailedConstructionError` if construction fails. + + If `PUGL_HPP_ASSERT_CONSTRUCTION` is defined, then this asserts if + construction fails. + + Otherwise, this does nothing. +*/ +# define PUGL_CHECK_CONSTRUCTION(cond, msg) +#endif + /// @copydoc PuglWorld class World : public detail::Wrapper { public: - explicit World(WorldType type, WorldFlags flags) - : Wrapper{puglNewWorld(static_cast(type), flags)} - , _clock(*this) + World(const World&) = delete; + World& operator=(const World&) = delete; + + World(World&&) = delete; + World& operator=(World&&) = delete; + + ~World() = default; + + World(WorldType type, WorldFlag flag) + : Wrapper{puglNewWorld(static_cast(type), + static_cast(flag))} { - if (!cobj()) { - throw std::runtime_error("Failed to create pugl::World"); - } + PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::World"); } - explicit World(WorldType type) - : World{type, {}} + World(WorldType type, WorldFlags flags) + : Wrapper{puglNewWorld(static_cast(type), flags)} { - if (!cobj()) { - throw std::runtime_error("Failed to create pugl::World"); - } + PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::World"); } - /// @copydoc puglGetNativeWorld - void* nativeWorld() { return puglGetNativeWorld(cobj()); } - - // TODO: setLogFunc + explicit World(WorldType type) + : World{type, WorldFlags{}} + {} - Status setLogLevel(const LogLevel level) - { - return static_cast( - puglSetLogLevel(cobj(), static_cast(level))); - } + /// @copydoc puglGetNativeWorld + void* nativeWorld() noexcept { return puglGetNativeWorld(cobj()); } /// @copydoc puglSetClassName - Status setClassName(const char* const name) + Status setClassName(const char* const name) noexcept { return static_cast(puglSetClassName(cobj(), name)); } /// @copydoc puglGetTime - double time() const { return puglGetTime(cobj()); } + double time() const noexcept { return puglGetTime(cobj()); } /// @copydoc puglUpdate - Status update(const double timeout) + Status update(const double timeout) noexcept { return static_cast(puglUpdate(cobj(), timeout)); } - - /// Return a clock that uses Pugl time - const Clock& clock() { return _clock; } - -private: - Clock _clock; }; -inline Clock::time_point -Clock::now() const -{ - return time_point{duration{_world.time()}}; -} - /** @} @defgroup viewxx View - @ingroup pugl_cxx - @copydoc view @{ */ @@ -358,10 +349,10 @@ enum class ViewHint { swapInterval, ///< @copydoc PUGL_SWAP_INTERVAL resizable, ///< @copydoc PUGL_RESIZABLE ignoreKeyRepeat, ///< @copydoc PUGL_IGNORE_KEY_REPEAT + refreshRate, ///< @copydoc PUGL_REFRESH_RATE }; -static_assert(ViewHint(PUGL_IGNORE_KEY_REPEAT) == ViewHint::ignoreKeyRepeat, - ""); +static_assert(ViewHint(PUGL_REFRESH_RATE) == ViewHint::refreshRate, ""); using ViewHintValue = PuglViewHintValue; ///< @copydoc PuglViewHintValue @@ -392,32 +383,71 @@ public: : Wrapper{puglNewView(world.cobj())} , _world(world) { - if (!cobj()) { - throw std::runtime_error("Failed to create pugl::View"); - } - - puglSetHandle(cobj(), this); - puglSetEventFunc(cobj(), dispatchEvent); + PUGL_CHECK_CONSTRUCTION(cobj(), "Failed to create pugl::View"); } - virtual ~View() = default; - - View(const View&) = delete; - View& operator=(const View&) = delete; + const World& world() const noexcept { return _world; } + World& world() noexcept { return _world; } - View(View&&) = delete; - View&& operator=(View&&) = delete; + /** + Set the object that will be called to handle events. + + This is a type-safe wrapper for the C functions puglSetHandle() and + puglSetEventFunc() that will automatically dispatch events to the + `onEvent` method of `handler` that takes the appropriate event type. + The handler must have such a method defined for every event type, but if + the handler is the view itself, a `using` declaration can be used to + "inherit" the default implementation to avoid having to define every + method. For example: + + @code + class MyView : public pugl::View + { + public: + explicit MyView(pugl::World& world) + : pugl::View{world} + { + setEventHandler(*this); + } + + using pugl::View::onEvent; + + pugl::Status onEvent(const pugl::ConfigureEvent& event) noexcept; + pugl::Status onEvent(const pugl::ExposeEvent& event) noexcept; + }; + @endcode + + This facility is just a convenience, applications may use the C API + directly to set a handle and event function to set up a different + approach for event handling. + */ + template + Status setEventHandler(Handler& handler) + { + puglSetHandle(cobj(), &handler); + return static_cast( + puglSetEventFunc(cobj(), eventFunc)); + } - const pugl::World& world() const { return _world; } - pugl::World& world() { return _world; } + /// @copydoc puglSetBackend + Status setBackend(const PuglBackend* backend) noexcept + { + return static_cast(puglSetBackend(cobj(), backend)); + } /// @copydoc puglSetViewHint - Status setHint(ViewHint hint, int value) + Status setHint(ViewHint hint, int value) noexcept { return static_cast( puglSetViewHint(cobj(), static_cast(hint), value)); } + /// @copydoc puglGetViewHint + int getHint(ViewHint hint) noexcept + { + return puglGetViewHint(cobj(), static_cast(hint)); + } + /** @} @name Frame @@ -426,34 +456,34 @@ public: */ /// @copydoc puglGetFrame - Rect frame() const { return puglGetFrame(cobj()); } + Rect frame() const noexcept { return puglGetFrame(cobj()); } /// @copydoc puglSetFrame - Status setFrame(Rect frame) + Status setFrame(Rect frame) noexcept { return static_cast(puglSetFrame(cobj(), frame)); } /// @copydoc puglSetDefaultSize - Status setDefaultSize(int width, int height) + Status setDefaultSize(int width, int height) noexcept { return static_cast(puglSetDefaultSize(cobj(), width, height)); } /// @copydoc puglSetMinSize - Status setMinSize(int width, int height) + Status setMinSize(int width, int height) noexcept { return static_cast(puglSetMinSize(cobj(), width, height)); } /// @copydoc puglSetMaxSize - Status setMaxSize(int width, int height) + Status setMaxSize(int width, int height) noexcept { return static_cast(puglSetMaxSize(cobj(), width, height)); } /// @copydoc puglSetAspectRatio - Status setAspectRatio(int minX, int minY, int maxX, int maxY) + Status setAspectRatio(int minX, int minY, int maxX, int maxY) noexcept { return static_cast( puglSetAspectRatio(cobj(), minX, minY, maxX, maxY)); @@ -467,37 +497,46 @@ public: */ /// @copydoc puglSetWindowTitle - Status setWindowTitle(const char* title) + Status setWindowTitle(const char* title) noexcept { return static_cast(puglSetWindowTitle(cobj(), title)); } /// @copydoc puglSetParentWindow - Status setParentWindow(NativeView parent) + Status setParentWindow(NativeView parent) noexcept { return static_cast(puglSetParentWindow(cobj(), parent)); } /// @copydoc puglSetTransientFor - Status setTransientFor(NativeView parent) + Status setTransientFor(NativeView parent) noexcept { return static_cast(puglSetTransientFor(cobj(), parent)); } /// @copydoc puglRealize - Status realize() { return static_cast(puglRealize(cobj())); } + Status realize() noexcept + { + return static_cast(puglRealize(cobj())); + } - /// @copydoc puglShowWindow - Status showWindow() { return static_cast(puglShowWindow(cobj())); } + /// @copydoc puglShow + Status show() noexcept + { + return static_cast(puglShow(cobj())); + } - /// @copydoc puglHideWindow - Status hideWindow() { return static_cast(puglHideWindow(cobj())); } + /// @copydoc puglHide + Status hide() noexcept + { + return static_cast(puglHide(cobj())); + } /// @copydoc puglGetVisible - bool visible() const { return puglGetVisible(cobj()); } + bool visible() const noexcept { return puglGetVisible(cobj()); } /// @copydoc puglGetNativeWindow - NativeView nativeWindow() { return puglGetNativeWindow(cobj()); } + NativeView nativeWindow() noexcept { return puglGetNativeWindow(cobj()); } /** @} @@ -508,16 +547,16 @@ public: */ /// @copydoc puglGetContext - void* context() { return puglGetContext(cobj()); } + void* context() noexcept { return puglGetContext(cobj()); } /// @copydoc puglPostRedisplay - Status postRedisplay() + Status postRedisplay() noexcept { return static_cast(puglPostRedisplay(cobj())); } /// @copydoc puglPostRedisplayRect - Status postRedisplayRect(const Rect rect) + Status postRedisplayRect(const Rect rect) noexcept { return static_cast(puglPostRedisplayRect(cobj(), rect)); } @@ -530,158 +569,133 @@ public: */ /// @copydoc puglGrabFocus - Status grabFocus() { return static_cast(puglGrabFocus(cobj())); } - - /// @copydoc puglHasFocus - bool hasFocus() const { return puglHasFocus(cobj()); } - - /// @copydoc puglSetBackend - Status setBackend(const PuglBackend* backend) + Status grabFocus() noexcept { - return static_cast(puglSetBackend(cobj(), backend)); + return static_cast(puglGrabFocus(cobj())); } + /// @copydoc puglHasFocus + bool hasFocus() const noexcept { return puglHasFocus(cobj()); } + /// @copydoc puglSetCursor - Status setCursor(const Cursor cursor) + Status setCursor(const Cursor cursor) noexcept { return static_cast( puglSetCursor(cobj(), static_cast(cursor))); } /// @copydoc puglRequestAttention - Status requestAttention() + Status requestAttention() noexcept { return static_cast(puglRequestAttention(cobj())); } - /** - @} - @name Event Handlers - Methods called when events are dispatched to the view. - @{ - */ + /// @copydoc puglStartTimer + Status startTimer(const uintptr_t id, const double timeout) noexcept + { + return static_cast(puglStartTimer(cobj(), id, timeout)); + } - virtual Status onCreate(const CreateEvent&) PUGL_CONST_FUNC; - virtual Status onDestroy(const DestroyEvent&) PUGL_CONST_FUNC; - virtual Status onConfigure(const ConfigureEvent&) PUGL_CONST_FUNC; - virtual Status onMap(const MapEvent&) PUGL_CONST_FUNC; - virtual Status onUnmap(const UnmapEvent&) PUGL_CONST_FUNC; - virtual Status onUpdate(const UpdateEvent&) PUGL_CONST_FUNC; - virtual Status onExpose(const ExposeEvent&) PUGL_CONST_FUNC; - virtual Status onClose(const CloseEvent&) PUGL_CONST_FUNC; - virtual Status onFocusIn(const FocusInEvent&) PUGL_CONST_FUNC; - virtual Status onFocusOut(const FocusOutEvent&) PUGL_CONST_FUNC; - virtual Status onKeyPress(const KeyPressEvent&) PUGL_CONST_FUNC; - virtual Status onKeyRelease(const KeyReleaseEvent&) PUGL_CONST_FUNC; - virtual Status onText(const TextEvent&) PUGL_CONST_FUNC; - virtual Status onPointerIn(const PointerInEvent&) PUGL_CONST_FUNC; - virtual Status onPointerOut(const PointerOutEvent&) PUGL_CONST_FUNC; - virtual Status onButtonPress(const ButtonPressEvent&) PUGL_CONST_FUNC; - virtual Status onButtonRelease(const ButtonReleaseEvent&) PUGL_CONST_FUNC; - virtual Status onMotion(const MotionEvent&) PUGL_CONST_FUNC; - virtual Status onScroll(const ScrollEvent&) PUGL_CONST_FUNC; - virtual Status onClient(const ClientEvent&) PUGL_CONST_FUNC; - virtual Status onTimer(const TimerEvent&) PUGL_CONST_FUNC; + /// @copydoc puglStopTimer + Status stopTimer(const uintptr_t id) noexcept + { + return static_cast(puglStopTimer(cobj(), id)); + } /** @} */ - PuglView* cobj() { return Wrapper::cobj(); } - const PuglView* cobj() const { return Wrapper::cobj(); } + PuglView* cobj() noexcept { return Wrapper::cobj(); } + const PuglView* cobj() const noexcept { return Wrapper::cobj(); } private: - template - static const Typed& typedEventRef(const Base& base) - { - const auto& event = static_cast(base); - static_assert(sizeof(event) == sizeof(typename Typed::BaseEvent), ""); - static_assert(std::is_standard_layout::value, ""); - assert(event.type == Typed::type); - return event; - } - - static PuglStatus dispatchEvent(PuglView* view, const PuglEvent* event) noexcept { - try { - View* self = static_cast(puglGetHandle(view)); - - return self->dispatch(event); - } catch (...) { - return PUGL_UNKNOWN_ERROR; - } - } - - PuglStatus dispatch(const PuglEvent* event) + template + static Status dispatch(Target& target, const PuglEvent* event) { switch (event->type) { case PUGL_NOTHING: - return PUGL_SUCCESS; + return Status::success; case PUGL_CREATE: - return static_cast( - onCreate(typedEventRef(event->any))); + return target.onEvent(static_cast(event->any)); case PUGL_DESTROY: - return static_cast( - onDestroy(typedEventRef(event->any))); + return target.onEvent(static_cast(event->any)); case PUGL_CONFIGURE: - return static_cast(onConfigure( - typedEventRef(event->configure))); + return target.onEvent( + static_cast(event->configure)); case PUGL_MAP: - return static_cast( - onMap(typedEventRef(event->any))); + return target.onEvent(static_cast(event->any)); case PUGL_UNMAP: - return static_cast( - onUnmap(typedEventRef(event->any))); + return target.onEvent(static_cast(event->any)); case PUGL_UPDATE: - return static_cast( - onUpdate(typedEventRef(event->any))); + return target.onEvent(static_cast(event->any)); case PUGL_EXPOSE: - return static_cast( - onExpose(typedEventRef(event->expose))); + return target.onEvent( + static_cast(event->expose)); case PUGL_CLOSE: - return static_cast( - onClose(typedEventRef(event->any))); + return target.onEvent(static_cast(event->any)); case PUGL_FOCUS_IN: - return static_cast( - onFocusIn(typedEventRef(event->focus))); + return target.onEvent( + static_cast(event->focus)); case PUGL_FOCUS_OUT: - return static_cast( - onFocusOut(typedEventRef(event->focus))); + return target.onEvent( + static_cast(event->focus)); case PUGL_KEY_PRESS: - return static_cast( - onKeyPress(typedEventRef(event->key))); + return target.onEvent( + static_cast(event->key)); case PUGL_KEY_RELEASE: - return static_cast( - onKeyRelease(typedEventRef(event->key))); + return target.onEvent( + static_cast(event->key)); case PUGL_TEXT: - return static_cast( - onText(typedEventRef(event->text))); + return target.onEvent(static_cast(event->text)); case PUGL_POINTER_IN: - return static_cast(onPointerIn( - typedEventRef(event->crossing))); + return target.onEvent( + static_cast(event->crossing)); case PUGL_POINTER_OUT: - return static_cast(onPointerOut( - typedEventRef(event->crossing))); + return target.onEvent( + static_cast(event->crossing)); case PUGL_BUTTON_PRESS: - return static_cast(onButtonPress( - typedEventRef(event->button))); + return target.onEvent( + static_cast(event->button)); case PUGL_BUTTON_RELEASE: - return static_cast(onButtonRelease( - typedEventRef(event->button))); + return target.onEvent( + static_cast(event->button)); case PUGL_MOTION: - return static_cast( - onMotion(typedEventRef(event->motion))); + return target.onEvent( + static_cast(event->motion)); case PUGL_SCROLL: - return static_cast( - onScroll(typedEventRef(event->scroll))); + return target.onEvent( + static_cast(event->scroll)); case PUGL_CLIENT: - return static_cast( - onClient(typedEventRef(event->client))); + return target.onEvent( + static_cast(event->client)); case PUGL_TIMER: - return static_cast( - onTimer(typedEventRef(event->timer))); + return target.onEvent(static_cast(event->timer)); + case PUGL_LOOP_ENTER: + return target.onEvent( + static_cast(event->any)); + case PUGL_LOOP_LEAVE: + return target.onEvent( + static_cast(event->any)); } - return PUGL_FAILURE; + return Status::failure; + } + + template + static PuglStatus eventFunc(PuglView* view, const PuglEvent* event) noexcept + { + auto* target = static_cast(puglGetHandle(view)); + +#ifdef __cpp_exceptions + try { + return static_cast(dispatch(*target, event)); + } catch (...) { + return PUGL_UNKNOWN_ERROR; + } +#else + return static_cast(pugl::dispatch(*target, event)); +#endif } World& _world; @@ -689,12 +703,9 @@ private: /** @} + @} */ } // namespace pugl -/** - @} -*/ - -#endif /* PUGL_PUGL_HPP */ +#endif // PUGL_PUGL_HPP diff --git a/pugl/pugl_stub.hpp b/bindings/cxx/include/pugl/stub.hpp similarity index 80% rename from pugl/pugl_stub.hpp rename to bindings/cxx/include/pugl/stub.hpp index c5f3901..8b37da4 100644 --- a/pugl/pugl_stub.hpp +++ b/bindings/cxx/include/pugl/stub.hpp @@ -14,16 +14,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/** - @file pugl_stub.hpp - @brief Declaration of Stub backend accessor for C++. -*/ - -#ifndef PUGL_PUGL_STUB_HPP -#define PUGL_PUGL_STUB_HPP +#ifndef PUGL_STUB_HPP +#define PUGL_STUB_HPP #include "pugl/pugl.h" -#include "pugl/pugl_stub.h" +#include "pugl/stub.h" namespace pugl { @@ -35,8 +30,8 @@ namespace pugl { */ /// @copydoc puglStubBackend -static inline const PuglBackend* -stubBackend() +inline const PuglBackend* +stubBackend() noexcept { return puglStubBackend(); } @@ -47,4 +42,4 @@ stubBackend() } // namespace pugl -#endif // PUGL_PUGL_STUB_HPP +#endif // PUGL_STUB_HPP diff --git a/bindings/cxx/include/pugl/vulkan.hpp b/bindings/cxx/include/pugl/vulkan.hpp new file mode 100644 index 0000000..65d1e57 --- /dev/null +++ b/bindings/cxx/include/pugl/vulkan.hpp @@ -0,0 +1,168 @@ +/* + Copyright 2012-2020 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/* + Note that this header includes Vulkan headers, so if you are writing a + program or plugin that dynamically loads vulkan, you should first define + `VK_NO_PROTOTYPES` before including it. +*/ + +#ifndef PUGL_VULKAN_HPP +#define PUGL_VULKAN_HPP + +#include "pugl/pugl.h" +#include "pugl/pugl.hpp" +#include "pugl/vulkan.h" + +#include + +#include + +namespace pugl { + +/** + @defgroup vulkanxx Vulkan + Vulkan graphics support. + + Note that the Pugl C++ wrapper does not use vulkan-hpp because it is a + heavyweight dependency which not everyone uses, and its design is not very + friendly to dynamic loading in plugins anyway. However, if you do use + vulkan-hpp smart handles, it is relatively straightforward to wrap the + result of createSurface() manually. + + @ingroup pugl_cxx + @{ +*/ + +/// @copydoc PuglVulkanLoader +class VulkanLoader final + : public detail::Wrapper +{ +public: + /** + Create a new dynamic loader for Vulkan functions. + + This dynamically loads the Vulkan library and gets the load functions + from it. + + Note that this constructor does not throw exceptions, though failure is + possible. To check if the Vulkan library failed to load, test this + loader, which is explicitly convertible to `bool`. It is safe to use a + failed loader, but the accessors will always return null. + */ + explicit VulkanLoader(World& world) noexcept + : Wrapper{puglNewVulkanLoader(world.cobj())} + {} + + /** + Return the `vkGetInstanceProcAddr` function. + + @return Null if the Vulkan library failed to load, or does not contain + this function (which is unlikely and indicates a broken system). + */ + PFN_vkGetInstanceProcAddr getInstanceProcAddrFunc() const noexcept + { + return cobj() ? puglGetInstanceProcAddrFunc(cobj()) : nullptr; + } + + /** + Return the `vkGetDeviceProcAddr` function. + + @return Null if the Vulkan library failed to load, or does not contain + this function (which is unlikely and indicates a broken system). + */ + PFN_vkGetDeviceProcAddr getDeviceProcAddrFunc() const noexcept + { + return cobj() ? puglGetDeviceProcAddrFunc(cobj()) : nullptr; + } + + /// Return true if this loader is valid to use + explicit operator bool() const noexcept { return cobj(); } +}; + +/** + A simple wrapper for an array of static C strings. + + This provides a minimal API that supports iteration, like `std::vector`, but + avoids allocation, exceptions, and a dependency on the C++ standard library. +*/ +class StaticStringArray final +{ +public: + using value_type = const char*; + using const_iterator = const char* const*; + using size_type = uint32_t; + + StaticStringArray(const char* const* strings, const uint32_t size) noexcept + : _strings{strings} + , _size{size} + {} + + const char* const* begin() const noexcept { return _strings; } + const char* const* end() const noexcept { return _strings + _size; } + const char* const* data() const noexcept { return _strings; } + uint32_t size() const noexcept { return _size; } + +private: + const char* const* _strings; + uint32_t _size; +}; + +/** + Return the Vulkan instance extensions required to draw to a PuglView. + + If successful, the returned array always contains "VK_KHR_surface", along + with whatever other platform-specific extensions are required. + + @return An array of extension name strings. +*/ +inline StaticStringArray +getInstanceExtensions() noexcept +{ + uint32_t count = 0; + const char* const* const extensions = puglGetInstanceExtensions(&count); + + return StaticStringArray{extensions, count}; +} + +/// @copydoc puglCreateSurface +inline VkResult +createSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, + View& view, + VkInstance instance, + const VkAllocationCallbacks* const allocator, + VkSurfaceKHR* const surface) noexcept +{ + const VkResult r = puglCreateSurface( + vkGetInstanceProcAddr, view.cobj(), instance, allocator, surface); + + return (!r && !surface) ? VK_ERROR_INITIALIZATION_FAILED : r; +} + +/// @copydoc puglVulkanBackend +inline const PuglBackend* +vulkanBackend() noexcept +{ + return puglVulkanBackend(); +} + +/** + @} +*/ + +} // namespace pugl + +#endif // PUGL_VULKAN_HPP diff --git a/doc/_static/custom.css b/doc/_static/custom.css new file mode 100644 index 0000000..60aa759 --- /dev/null +++ b/doc/_static/custom.css @@ -0,0 +1,95 @@ +div.document { + margin: 0; +} + +div.body { + margin-top: 2em; +} + +div.sphinxsidebarwrapper { + background: #EEE; +} + +div.sphinxsidebarwrapper p.blurb { + text-align: center; +} + +div.sphinxsidebarwrapper span.logo { + display: block; + text-align: center; + font-family: Georgia, serif; + padding: 0; + font-size: 180%; +} + +div.sphinxsidebar a { + border-width: 0; +} + +div.sphinxsidebar li { + color: #444; +} + +div.section { + margin-top: 2.5em; +} + +a.reference { + border-bottom: none; +} + +code.xref { + font-weight: normal; + background-color: #F8F8F8; + padding: 0.1em 0 0.1em 0; +} + +div.section > dl.c > dt:first-child, +div.section > dl.cpp > dt:first-child { + background-color: #F8F8F8; + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; + font-weight: normal; + margin-bottom: 0.5em; + padding: 0.1em 0 0.1em 0; +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.9em; +} + +dl.member { + margin-top: 0.5em; +} + +dl.enumerator { + margin-top: 0.5em; +} + +dl.field-list > dt { + padding-left: 0; +} + +pre, tt, code { + background-color: #F8F8F8; +} + +.toctree-l1 { + margin-top: 1.0em; +} + +img.logo { + width: 6em; +} + +.class { + padding-top: 1.5em; +} + +.exception { + padding-top: 1.5em; +} + +.class > dd > dl.function { + padding-top: 1.0em; +} diff --git a/doc/_templates/about.html b/doc/_templates/about.html new file mode 100644 index 0000000..5bbadbe --- /dev/null +++ b/doc/_templates/about.html @@ -0,0 +1,57 @@ +{% if theme_logo %} + +{% else %} +

{{ project }}

+{% endif %} + +{% if theme_description %} +

{{ theme_description }}

+{% endif %} + +{% if theme_github_user and theme_github_repo %} +{% if theme_github_button|lower == 'true' %} +

+ +

+{% endif %} +{% endif %} + +{% if theme_travis_button|lower != 'false' %} +{% if theme_travis_button|lower == 'true' %} + {% set path = theme_github_user + '/' + theme_github_repo %} +{% else %} + {% set path = theme_travis_button %} +{% endif %} +

+ + https://secure.travis-ci.org/{{ path }}.svg?branch={{ theme_badge_branch }} + +

+{% endif %} + +{% if theme_codecov_button|lower != 'false' %} +{% if theme_codecov_button|lower == 'true' %} + {% set path = theme_github_user + '/' + theme_github_repo %} +{% else %} + {% set path = theme_codecov_button %} +{% endif %} +

+ + https://codecov.io/github/{{ path }}/coverage.svg?branch={{ theme_badge_branch }} + +

+{% endif %} diff --git a/doc/c/Doxyfile b/doc/c/Doxyfile new file mode 100644 index 0000000..fe56f0b --- /dev/null +++ b/doc/c/Doxyfile @@ -0,0 +1,30 @@ +PROJECT_NAME = Pugl +PROJECT_BRIEF = "A minimal portable API for embeddable GUIs" + +QUIET = YES +WARN_AS_ERROR = NO +WARN_IF_UNDOCUMENTED = NO +WARN_NO_PARAMDOC = NO + +JAVADOC_AUTOBRIEF = YES + +CASE_SENSE_NAMES = YES +HIDE_IN_BODY_DOCS = YES +REFERENCES_LINK_SOURCE = NO + +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_PROGRAMLISTING = NO +SHOW_FILES = NO + +MACRO_EXPANSION = YES +PREDEFINED = PUGL_API PUGL_DISABLE_DEPRECATED PUGL_CONST_FUNC= + +INPUT = ../../include/pugl/cairo.h \ + ../../include/pugl/gl.h \ + ../../include/pugl/pugl.h \ + ../../include/pugl/stub.h \ + ../../include/pugl/vulkan.h + +OUTPUT_DIRECTORY = . diff --git a/doc/c/index.rst b/doc/c/index.rst new file mode 100644 index 0000000..6f046de --- /dev/null +++ b/doc/c/index.rst @@ -0,0 +1,6 @@ +.. toctree:: + + pugl + deployment + overview + reference diff --git a/doc/c/overview.rst b/doc/c/overview.rst new file mode 100644 index 0000000..3ebe21e --- /dev/null +++ b/doc/c/overview.rst @@ -0,0 +1,579 @@ +.. default-domain:: c +.. highlight:: c + +The core API (excluding backend-specific components) is declared in ``pugl.h``: + +.. code-block:: c + + #include + +The API revolves around two main objects: the `world` and the `view`. +An application creates a world to manage top-level state, +then creates one or more views to display. + +**************** +Creating a World +**************** + +The world is the top-level object which represents an instance of Pugl. +It handles the connection to the window system, +and manages views and the event loop. + +An application typically has a single world, +which is constructed once on startup and used to drive the main event loop. + +Construction +============ + +A world must be created before any views, and it must outlive all of its views. +A world is created with :func:`puglNewWorld`, for example: + +.. code-block:: c + + PuglWorld* world = puglNewWorld(PUGL_PROGRAM, 0); + +For a plugin, specify :enumerator:`PUGL_MODULE ` instead. +In some cases, it is necessary to pass additional flags. +For example, Vulkan requires thread support: + +.. code-block:: c + + PuglWorld* world = puglNewWorld(PUGL_MODULE, PUGL_WORLD_THREADS) + +It is a good idea to set a class name for your project with :func:`puglSetClassName`. +This allows the window system to distinguish different applications and, +for example, users to set up rules to manage their windows nicely: + +.. code-block:: c + + puglSetClassName(world, "MyAwesomeProject") + +Setting Application Data +======================== + +Pugl will call an event handler in the application with only a view pointer and an event, +so there needs to be some way to access the data you use in your application. +This is done by setting an opaque handle on the world with :func:`puglSetWorldHandle`, +for example: + +.. code-block:: c + + puglSetWorldHandle(world, myApp); + +The handle can be later retrieved with :func:`puglGetWorldHandle`: + +.. code-block:: c + + MyApp* app = (MyApp*)puglGetWorldHandle(world); + +All non-constant data should be accessed via this handle, +to avoid problems associated with static mutable data. + +*************** +Creating a View +*************** + +A view is a drawable region that receives events. +You may think of it as a window, +though it may be embedded and not represent a top-level system window. [#f1]_ + +Creating a visible view is a multi-step process. +When a new view is created with :func:`puglNewView`, +it does not yet represent a "real" system view: + +.. code-block:: c + + PuglView* view = puglNewView(world); + +Configuring the Frame +===================== + +Before display, +the necessary :doc:`frame ` and :doc:`window ` attributes should be set. +These allow the window system (or plugin host) to arrange the view properly. +For example: + +.. code-block:: c + + const double defaultWidth = 1920.0; + const double defaultHeight = 1080.0; + + puglSetWindowTitle(view, "My Window"); + puglSetDefaultSize(view, defaultWidth, defaultHeight); + puglSetMinSize(view, defaultWidth / 4.0, defaultHeight / 4.0); + puglSetAspectRatio(view, 1, 1, 16, 9); + +There are also several :enum:`hints ` for basic attributes that can be set: + +.. code-block:: c + + puglSetViewHint(view, PUGL_RESIZABLE, PUGL_TRUE); + puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, PUGL_TRUE); + +Embedding +========= + +To embed the view in another window, +you will need to somehow get the :type:`native view handle ` for the parent, +then set it with :func:`puglSetParentWindow`. +If the parent is a Pugl view, +the native handle can be accessed with :func:`puglGetNativeWindow`. +For example: + +.. code-block:: c + + puglSetParentWindow(view, puglGetNativeWindow(parent)); + +Setting an Event Handler +======================== + +In order to actually do anything, a view must process events from the system. +Pugl dispatches all events to a single :type:`event handling function `, +which is set with :func:`puglSetEventFunc`: + +.. code-block:: c + + puglSetEventFunc(view, onEvent); + +See `Handling Events`_ below for details on writing the event handler itself. + +Setting View Data +================= + +Since the event handler is called with only a view pointer and an event, +there needs to be some way to access application data associated with the view. +Similar to `Setting Application Data`_ above, +this is done by setting an opaque handle on the view with :func:`puglSetHandle`, +for example: + +.. code-block:: c + + puglSetHandle(view, myViewData); + +The handle can be later retrieved, +likely in the event handler, +with :func:`puglGetHandle`: + +.. code-block:: c + + MyViewData* data = (MyViewData*)puglGetHandle(view); + +All non-constant data should be accessed via this handle, +to avoid problems associated with static mutable data. + +If data is also associated with the world, +it can be retrieved via the view using :func:`puglGetWorld`: + +.. code-block:: c + + PuglWorld* world = puglGetWorld(view); + MyApp* app = (MyApp*)puglGetWorldHandle(world); + +Setting a Backend +================= + +Before being realized, the view must have a backend set with :func:`puglSetBackend`. + +The backend manages the graphics API that will be used for drawing. +Pugl includes backends and supporting API for +:doc:`Cairo `, :doc:`OpenGL `, and :doc:`Vulkan `. + +Using Cairo +----------- + +Cairo-specific API is declared in the ``cairo.h`` header: + +.. code-block:: c + + #include + +The Cairo backend is provided by :func:`puglCairoBackend()`: + +.. code-block:: c + + puglSetBackend(view, puglCairoBackend()); + +No additional configuration is required for Cairo. +To draw when handling an expose event, +the `Cairo context `_ can be accessed with :func:`puglGetContext`: + +.. code-block:: c + + cairo_t* cr = (cairo_t*)puglGetContext(view); + +Using OpenGL +------------ + +OpenGL-specific API is declared in the ``gl.h`` header: + +.. code-block:: c + + #include + +The OpenGL backend is provided by :func:`puglGlBackend()`: + +.. code-block:: c + + puglSetBackend(view, puglGlBackend()); + +Some hints must also be set so that the context can be set up correctly. +For example, to use OpenGL 3.3 Core Profile: + +.. code-block:: c + + puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE); + puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 3); + puglSetViewHint(view, PUGL_CONTEXT_VERSION_MINOR, 3); + +If you need to perform some setup using the OpenGL API, +there are two ways to do so. + +The OpenGL context is active when +:enumerator:`PUGL_CREATE ` and +:enumerator:`PUGL_DESTROY ` +events are dispatched, +so things like creating and destroying shaders and textures can be done then. + +Alternatively, if it is cumbersome to set up and tear down OpenGL in the event handler, +:func:`puglEnterContext` and :func:`puglLeaveContext` can be used to manually activate the OpenGL context during application setup. +Note, however, that unlike many other APIs, these functions must not be used for drawing. +It is only valid to use the OpenGL API for configuration in a manually entered context, +rendering will not work. +For example: + +.. code-block:: c + + puglEnterContext(view); + setupOpenGL(myApp); + puglLeaveContext(view); + + while (!myApp->quit) { + puglUpdate(world, 0.0); + } + + puglEnterContext(view); + teardownOpenGL(myApp); + puglLeaveContext(view); + +Using Vulkan +------------ + +Vulkan-specific API is declared in the ``vulkan.h`` header. +This header includes Vulkan headers, +so if you are dynamically loading Vulkan at runtime, +you should define ``VK_NO_PROTOTYPES`` before including it. + +.. code-block:: c + + #define VK_NO_PROTOTYPES + + #include + +The Vulkan backend is provided by :func:`puglVulkanBackend()`: + +.. code-block:: c + + puglSetBackend(view, puglVulkanBackend()); + +Unlike OpenGL, almost all Vulkan configuration is done using the Vulkan API directly. +Pugl only provides a portable mechanism to load the Vulkan library and get the functions used to load the rest of the Vulkan API. + +Loading Vulkan +^^^^^^^^^^^^^^ + +For maximum compatibility, +it is best to not link to Vulkan at compile-time, +but instead load the Vulkan API at run-time. +To do so, first create a :struct:`PuglVulkanLoader`: + +.. code-block:: c + + PuglVulkanLoader* loader = puglNewVulkanLoader(world); + +The loader manages the dynamically loaded Vulkan library, +so it must be kept alive for as long as the application is using Vulkan. +You can get the function used to load Vulkan functions with :func:`puglGetInstanceProcAddrFunc`: + +.. code-block:: c + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + puglGetInstanceProcAddrFunc(loader); + +This vkGetInstanceProcAddr_ function can be used to load the rest of the Vulkan API. +For example, you can use it to get the vkCreateInstance_ function, +then use that to create your Vulkan instance. +In practice, you will want to use some loader or wrapper API since there are many Vulkan functions. + +For advanced situations, +there is also :func:`puglGetDeviceProcAddrFunc` which retrieves the vkGetDeviceProcAddr_ function instead. + +The Vulkan loader is provided for convenience, +so that applications to not need to write platform-specific code to load Vulkan. +Its use it not mandatory and Pugl can be used with Vulkan loaded by some other method. + +Linking with Vulkan +^^^^^^^^^^^^^^^^^^^ + +If you do want to link to the Vulkan library at compile time, +note that the Pugl Vulkan backend does not depend on it, +so you will have to do so explicitly. + +Creating a Surface +^^^^^^^^^^^^^^^^^^ + +The details of using Vulkan are far beyond the scope of this documentation, +but Pugl provides a portable function, :func:`puglCreateSurface`, +to get the Vulkan surface for a view. +Assuming you have somehow created your ``VkInstance``, +you can get the surface for a view using :func:`puglCreateSurface`: + +.. code-block:: c + + VkSurfaceKHR* surface = NULL; + puglCreateSurface(puglGetDeviceProcAddrFunc(loader), + view, + vulkanInstance, + NULL, + &surface); + +Showing the View +================ + +Once the view is configured, it can be "realized" with :func:`puglRealize`. +This creates a "real" system view, for example: + +.. code-block:: c + + PuglStatus status = puglRealize(view); + if (status) { + fprintf(stderr, "Error realizing view (%s)\n", puglStrerror(status)); + } + +Note that realizing a view can fail for many reasons, +so the return code should always be checked. +This is generally the case for any function that interacts with the window system. +Most functions also return a :enum:`PuglStatus`, +but these checks are omitted for brevity in the rest of this documentation. + +A realized view is not initially visible, +but can be shown with :func:`puglShow`: + +.. code-block:: c + + puglShow(view); + +To create an initially visible view, +it is also possible to simply call :func:`puglShow` right away. +The view will be automatically realized if necessary. + +*************** +Handling Events +*************** + +Events are sent to a view when it has received user input, +must be drawn, or in other situations that may need to be handled such as resizing. + +Events are sent to the event handler as a :union:`PuglEvent` union. +The ``type`` field defines the type of the event and which field of the union is active. +The application must handle at least :enumerator:`PUGL_CONFIGURE ` +and :enumerator:`PUGL_EXPOSE ` to draw anything, +but there are many other :enum:`event types `. + +For example, a basic event handler might look something like this: + +.. code-block:: c + + static PuglStatus + onEvent(PuglView* view, const PuglEvent* event) + { + MyApp* app = (MyApp*)puglGetHandle(view); + + switch (event->type) { + case PUGL_CREATE: + return setupGraphics(app); + case PUGL_DESTROY: + return teardownGraphics(app); + case PUGL_CONFIGURE: + return resize(app, event->configure.width, event->configure.height); + case PUGL_EXPOSE: + return draw(app, view); + case PUGL_CLOSE: + return quit(app); + case PUGL_BUTTON_PRESS: + return onButtonPress(app, view, event->button); + default: + break; + } + + return PUGL_SUCCESS; + } + +Using the Graphics Context +========================== + +Drawing +------- + +Note that Pugl uses a different drawing model than many libraries, +particularly those designed for game-style main loops like `SDL `_ and `GLFW `_. + +In that style of code, drawing is performed imperatively in the main loop, +but with Pugl, the application must draw only while handling an expose event. +This is because Pugl supports event-driven applications that only draw the damaged region when necessary, +and handles exposure internally to provide optimized and consistent behavior across platforms. + +Cairo Context +------------- + +A Cairo context is created for each :struct:`PuglEventExpose`, +and only exists during the handling of that event. +Null is returned by :func:`puglGetContext` at any other time. + +OpenGL Context +-------------- + +The OpenGL context is only active during the handling of these events: + +- :struct:`PuglEventCreate` +- :struct:`PuglEventDestroy` +- :struct:`PuglEventConfigure` +- :struct:`PuglEventExpose` + +As always, drawing is only possible during an expose. + +Vulkan Context +-------------- + +With Vulkan, the graphics context is managed by the application rather than Pugl. +However, drawing must still only be performed during an expose. + +********************** +Driving the Event Loop +********************** + +Pugl does not contain any threads or other event loop "magic". +For flexibility, the event loop is driven explicitly by repeatedly calling :func:`puglUpdate`, +which processes events from the window system and dispatches them to views when necessary. + +The exact use of :func:`puglUpdate` depends on the application. +Plugins should call it with a ``timeout`` of 0 in a callback driven by the host. +This avoids blocking the main loop, +since other plugins and the host itself need to run as well. + +A program can use whatever timeout is appropriate: +event-driven applications may wait forever by using a ``timeout`` of -1, +while those that draw continuously may use a significant fraction of the frame period +(with enough time left over to render). + +Redrawing +========= + +Occasional redrawing can be requested by calling :func:`puglPostRedisplay` or :func:`puglPostRedisplayRect`. +After these are called, +a :struct:`PuglEventExpose` will be dispatched on the next call to :func:`puglUpdate`. + +For continuous redrawing, +call :func:`puglPostRedisplay` while handling a :struct:`PuglEventUpdate` event. +This event is sent just before views are redrawn, +so it can be used as a hook to expand the update region right before the view is exposed. +Anything else that needs to be done every frame can be handled similarly. + +Event Dispatching +================= + +Ideally, pending events are dispatched during a call to :func:`puglUpdate`, +directly within the scope of that call. + +Unfortunately, this is not universally true due to differences between platforms. + +MacOS +----- + +On MacOS, drawing is handled specially and not by the normal event queue mechanism. +This means that configure and expose events, +and possibly others, +may be dispatched to a view outside the scope of a :func:`puglUpdate` call. +In general, you can not rely on coherent event dispatching semantics on MacOS: +the operating system can call into application code at "random" times, +and these calls may result in Pugl events being dispatched. + +An application that follows the Pugl guidelines should work fine, +but there is one significant inconsistency you may encounter on MacOS: +posting a redisplay will not wake up a blocked :func:`puglUpdate` call. + +Windows +------- + +On Windows, the application has relatively tight control over the event loop, +so events are typically dispatched explicitly by :func:`puglUpdate`. +Drawing is handled by events, +so posting a redisplay will wake up a blocked :func:`puglUpdate` call. + +However, it is possible for the system to dispatch events at other times. +So, +it is possible for events to be dispatched outside the scope of a :func:`puglUpdate` call, +but this does not happen in normal circumstances and can largely be ignored. + +X11 +--- + +On X11, the application strictly controls event dispatching, +and there is no way for the system to call into application code at surprising times. +So, all events are dispatched in the scope of a :func:`puglUpdate` call. + +Recursive Event Loops +--------------------- + +On Windows and MacOS, +the event loop is stalled while the user is resizing the window or, +on Windows, +has displayed the window menu. +This means that :func:`puglUpdate` will block until the resize is finished, +or the menu is closed. + +Pugl dispatches :struct:`PuglEventLoopEnter` and :struct:`PuglEventLoopLeave` events to notify the application of this situation. +If you want to continuously redraw during resizing on these platforms, +you can schedule a timer with :func:`puglStartTimer` when the recursive loop is entered, +and post redisplays when handling the :struct:`PuglEventTimer`. +Be sure to remove the timer with :func:`puglStopTimer` when the recursive loop is finished. + +On X11, there are no recursive event loops, +and everything works as usual while the user is resizing the window. +There is nothing special about a "live resize" on X11, +and the above loop events will never be dispatched. + +************* +Shutting Down +************* + +When a view is closed, +it will receive a :struct:`PuglEventClose`. +An application may also set a flag based on user input or other conditions, +which can be used to break out of the main loop and stop calling :func:`puglUpdate`. + +When the main event loop has finished running, +any views and the world need to be destroyed, in that order. +For example: + +.. code-block:: c + + puglFreeView(view); + puglFreeWorld(world); + +.. _pkg-config: https://www.freedesktop.org/wiki/Software/pkg-config/ + +.. _vkCreateInstance: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCreateInstance.html + +.. _vkGetDeviceProcAddr: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetDeviceProcAddr.html + +.. _vkGetInstanceProcAddr: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetInstanceProcAddr.html + +.. rubric:: Footnotes + +.. [#f1] MacOS has a strong distinction between + `views `_, + which may be nested, and + `windows `_, + which may not. + On Windows and X11, everything is a nestable window, + but top-level windows are configured differently. diff --git a/doc/c/reference.rst b/doc/c/reference.rst new file mode 100644 index 0000000..21a187f --- /dev/null +++ b/doc/c/reference.rst @@ -0,0 +1,18 @@ +############# +API Reference +############# + +This section contains the generated documentation for all symbols in the public +API. + +.. toctree:: + + api/status + api/world + api/view + api/events + + api/cairo + api/gl + api/stub + api/vulkan diff --git a/doc/c/wscript b/doc/c/wscript new file mode 100644 index 0000000..4e0fbc9 --- /dev/null +++ b/doc/c/wscript @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +def build(bld): + dox_to_sphinx = bld.path.find_node("../../scripts/dox_to_sphinx.py") + index_xml = bld.path.get_bld().make_node("xml/index.xml") + + files = [ + ("../../resources/pugl.svg", "sphinx/_static/pugl.svg"), + ("../_static/custom.css", "sphinx/_static/custom.css"), + ("../_templates/about.html", "sphinx/_templates/about.html"), + ("../deployment.rst", "sphinx/deployment.rst"), + ("../pugl.rst", "sphinx/pugl.rst"), + ("index.rst", "sphinx/index.rst"), + ("overview.rst", "sphinx/overview.rst"), + ("reference.rst", "sphinx/reference.rst"), + ] + + # Run Doxygen to generate XML documentation + bld(features="doxygen", doxyfile="Doxyfile") + + # Substitute variables to make Sphinx configuration file + bld(features="subst", + source="../conf.py.in", + target="sphinx/conf.py", + PUGL_VERSION=bld.env.PUGL_VERSION) + + # Copy static documentation files to Sphinx build directory + for f in files: + bld(features="subst", is_copy=True, source=f[0], target=f[1]) + + # Generate Sphinx markup from Doxygen XML + bld.add_group() + bld(rule="${PYTHON} " + dox_to_sphinx.abspath() + " -f ${SRC} ${TGT}", + source=index_xml, + target="sphinx/api/") + + # Run Sphinx to generate HTML documentation + doc_dir = bld.env.DOCDIR + "/pugl-%s/" % bld.env.PUGL_MAJOR_VERSION + bld(features="sphinx", + sphinx_source=bld.path.get_bld().make_node("sphinx"), + sphinx_output_format="singlehtml", + sphinx_options=["-E", "-q"], + install_path=doc_dir + "c/singlehtml/") diff --git a/doc/conf.py.in b/doc/conf.py.in new file mode 100644 index 0000000..9ca7bfa --- /dev/null +++ b/doc/conf.py.in @@ -0,0 +1,88 @@ +# Project information + +project = "Pugl" +copyright = "2020, David Robillard" +author = "David Robillard" +release = "@PUGL_VERSION@" + +# General configuration + +language = "en" + +extensions = [ + # 'breathe', + # 'sphinx_rtd_theme', + # 'sphinx.ext.autodoc', + # 'sphinx.ext.doctest', + # 'sphinx.ext.napoleon', + # 'sphinx.ext.viewcode', +] + +# Enable nitpicky mode to get warnings about broken links +# Unfortunately this means we need to explicitly ignore everything external +nitpicky = True +_opaque = [ + "PFN_vkGetDeviceProcAddr", + "PFN_vkGetInstanceProcAddr", + "PuglBackendImpl", + "PuglViewImpl", + "PuglVulkanLoaderImpl", + "PuglWorldImpl", + "VkAllocationCallbacks", + "VkInstance", + "VkResult", + "VkSurfaceKHR", + "size_t", + "uint32_t", + "uintptr_t", +] +_c_nitpick_ignore = map(lambda x: ("c:identifier", x), _opaque) +_cpp_nitpick_ignore = map(lambda x: ("cpp:identifier", x), _opaque) +nitpick_ignore = list(_c_nitpick_ignore) + list(_cpp_nitpick_ignore) + +templates_path = ["_templates"] + +pygments_style = "friendly" + +# C++ + +cpp_index_common_prefix = ["pugl::"] + +# HTML output + +exclude_patterns = ["xml"] +html_static_path = ["_static"] + +html_theme = "alabaster" +# html_theme = "sphinx_rtd_theme" + +if html_theme == "alabaster": + + html_theme_options = { + "description": "A minimal portable API for embeddable GUIs.", + "donate_url": "http://drobilla.net/pages/donate.html", + # "github_repo": "pugl", + # "github_user": "lv2", + "logo": "pugl.svg", + "logo_name": True, + "logo_text_align": "center", + "page_width": "80em - 20em", + "sidebar_width": "20em", + } + + html_sidebars = { + "**": [ + "about.html", + "localtoc.html", + "donate.html", + ] + } + +elif html_theme == "sphinx_rtd_theme": + + html_theme_options = { + "sticky_navigation": False, + "collapse_navigation": False, + "navigation_depth": 4, + "display_version": True, + } diff --git a/doc/cpp/Doxyfile b/doc/cpp/Doxyfile new file mode 100644 index 0000000..2bb0f9f --- /dev/null +++ b/doc/cpp/Doxyfile @@ -0,0 +1,40 @@ +PROJECT_NAME = Pugl +PROJECT_BRIEF = "A minimal portable API for embeddable GUIs" + +QUIET = YES +WARN_AS_ERROR = NO +WARN_IF_UNDOCUMENTED = NO +WARN_NO_PARAMDOC = NO + +JAVADOC_AUTOBRIEF = YES + +CASE_SENSE_NAMES = YES +EXCLUDE_SYMBOLS = pugl::detail +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_PRIVATE = NO +HIDE_IN_BODY_DOCS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_UNDOC_MEMBERS = YES +REFERENCES_LINK_SOURCE = NO + +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_PROGRAMLISTING = NO +SHOW_FILES = NO + +MACRO_EXPANSION = YES +PREDEFINED = PUGL_API PUGL_DISABLE_DEPRECATED PUGL_CONST_FUNC= + +INPUT = ../../include/pugl/cairo.h \ + ../../include/pugl/gl.h \ + ../../include/pugl/pugl.h \ + ../../include/pugl/stub.h \ + ../../include/pugl/vulkan.h \ + ../../bindings/cxx/include/pugl/cairo.hpp \ + ../../bindings/cxx/include/pugl/gl.hpp \ + ../../bindings/cxx/include/pugl/pugl.hpp \ + ../../bindings/cxx/include/pugl/stub.hpp \ + ../../bindings/cxx/include/pugl/vulkan.hpp + +OUTPUT_DIRECTORY = . diff --git a/doc/cpp/c-reference.rst b/doc/cpp/c-reference.rst new file mode 100644 index 0000000..546e4d3 --- /dev/null +++ b/doc/cpp/c-reference.rst @@ -0,0 +1,20 @@ +############### +C API Reference +############### + +This section contains the generated documentation for all symbols in the public +C API. +It is included here because some C++ wrapper definitions refer to the underlying C symbols, +but direct use of the C API should not be necessary in C++ applications. + +.. toctree:: + + api/status + api/world + api/view + api/events + + api/cairo + api/gl + api/stub + api/vulkan diff --git a/doc/cpp/cpp-reference.rst b/doc/cpp/cpp-reference.rst new file mode 100644 index 0000000..96c523c --- /dev/null +++ b/doc/cpp/cpp-reference.rst @@ -0,0 +1,18 @@ +################# +C++ API Reference +################# + +This section contains the generated documentation for all symbols in the public +C++ API. + +.. toctree:: + + api/statusxx + api/worldxx + api/viewxx + api/eventsxx + + api/cairoxx + api/glxx + api/stubxx + api/vulkanxx diff --git a/doc/cpp/index.rst b/doc/cpp/index.rst new file mode 100644 index 0000000..c3d330e --- /dev/null +++ b/doc/cpp/index.rst @@ -0,0 +1,7 @@ +.. toctree:: + + pugl + deployment + overview + cpp-reference + c-reference diff --git a/doc/cpp/overview.rst b/doc/cpp/overview.rst new file mode 100644 index 0000000..5fffe37 --- /dev/null +++ b/doc/cpp/overview.rst @@ -0,0 +1,423 @@ +.. default-domain:: cpp +.. highlight:: cpp +.. namespace:: pugl + +Pugl is a C library, +but the bindings documented here provide a more idiomatic and type-safe API for C++. +If you would rather use C, +refer instead to the `C API documentation <../../c/singlehtml/index.html>`_. + +The C++ bindings are very lightweight and do not require virtual functions, +RTTI, +exceptions, +or linking to the C++ standard library. +They are provided by the package ``puglxx-0`` which must be used in addition to the desired platform+backend package above. + +The core API (excluding backend-specific components) is declared in ``pugl.hpp``: + +.. code-block:: cpp + + #include + +The API revolves around two main objects: the `world` and the `view`. +An application creates a world to manage top-level state, +then creates one or more views to display. + +Creating a World +================ + +The world is the top-level object which represents an instance of Pugl. +It handles the connection to the window system, +and manages views and the event loop. + +An application typically has a single world, +which is constructed once on startup and used to drive the main event loop. + +Construction +------------ + +A world must be created before any views, and it must outlive all of its views. +The world constructor requires an argument to specify the application type: + +.. code-block:: cpp + + pugl::World world{pugl::WorldType::program}; + +For a plugin, specify :enumerator:`WorldType::module` instead. +In some cases, it is necessary to pass additional flags. +For example, Vulkan requires thread support: + +.. code-block:: cpp + + pugl::World world{pugl::WorldType::program, pugl::WorldFlag::threads}; + +It is a good idea to set a class name for your project with :func:`World::setClassName`. +This allows the window system to distinguish different applications and, +for example, users to set up rules to manage their windows nicely: + +.. code-block:: cpp + + world.setClassName("MyAwesomeProject"); + +Creating a View +=============== + +A `view` is a drawable region that receives events. +You may think of it as a window, +though it may be embedded and not represent a top-level system window. [#f1]_ + +Pugl communicates with views by dispatching events. +For flexibility, the event handler can be a different object than the view. +This allows using :class:`View` along with a separate event handler class. +Alternatively, a view class can inherit from :class:`View` and set itself as its event handler, +for a more object-oriented style. + +This documentation will use the latter approach, +so we will define a class for our view that contains everything needed: + +.. code-block:: cpp + + class MyView : public pugl::View + { + public: + explicit MyView(pugl::World& world) + : pugl::View{world} + { + setEventHandler(*this); + } + + pugl::Status onEvent(const pugl::ConfigureEvent& event) noexcept; + pugl::Status onEvent(const pugl::ExposeEvent& event) noexcept; + + // With other handlers here as needed... + + // Fallback handler for all other events + template + pugl::Status onEvent(const pugl::Event&) noexcept + { + return pugl::Status::success; + } + + private: + // Some data... + }; + +Pugl will call an ``onEvent`` method of the event handler (the view in this case) for every event. + +Note that Pugl uses a static dispatching mechanism rather than virtual functions to minimize overhead. +It is therefore necessary for the final class to define a handler for every event type. +A terse way to do this without writing every implementation is to define a fallback handler as a template, +as in the example above. +Alternatively, you can define an explicit handler for each event that simply returns :enumerator:`Status::success`. +This way, it will be a compile error if any event is not explicitly handled. + +Configuring the Frame +--------------------- + +Before display, +the necessary :doc:`frame ` and :doc:`window ` attributes should be set. +These allow the window system (or plugin host) to arrange the view properly. + +Derived classes can configure themselves during construction, +but we assume here that configuration is being done outside the view. +For example: + +.. code-block:: cpp + + const double defaultWidth = 1920.0; + const double defaultHeight = 1080.0; + + view.setWindowTitle("My Window"); + view.setDefaultSize(defaultWidth, defaultHeight); + view.setMinSize(defaultWidth / 4.0, defaultHeight / 4.0); + view.setAspectRatio(1, 1, 16, 9); + +There are also several :type:`hints ` for basic attributes that can be set: + +.. code-block:: cpp + + view.setHint(pugl::ViewHint::resizable, true); + view.setHint(pugl::ViewHint::ignoreKeyRepeat, true); + +Embedding +--------- + +To embed the view in another window, +you will need to somehow get the :type:`native view handle ` for the parent, +then set it with :func:`View::setParentWindow`. +If the parent is a Pugl view, +the native handle can be accessed with :func:`View::nativeWindow`. +For example: + +.. code-block:: cpp + + view.setParentWindow(view, parent.getNativeWindow()); + +Setting a Backend +----------------- + +Before being realized, the view must have a backend set with :func:`View::setBackend`. + +The backend manages the graphics API that will be used for drawing. +Pugl includes backends and supporting API for +:doc:`Cairo `, :doc:`OpenGL `, and :doc:`Vulkan `. + +Using Cairo +^^^^^^^^^^^ + +Cairo-specific API is declared in the ``cairo.hpp`` header: + +.. code-block:: cpp + + #include + +The Cairo backend is provided by :func:`cairoBackend()`: + +.. code-block:: cpp + + view.setBackend(pugl::cairoBackend()); + +No additional configuration is required for Cairo. +To draw when handling an expose event, +the `Cairo context `_ can be accessed with :func:`View::context`: + +.. code-block:: cpp + + cairo_t* cr = static_cast(view.context()); + +Using OpenGL +^^^^^^^^^^^^ + +OpenGL-specific API is declared in the ``gl.hpp`` header: + +.. code-block:: cpp + + #include + +The OpenGL backend is provided by :func:`glBackend()`: + +.. code-block:: cpp + + view.setBackend(pugl::glBackend()); + +Some hints must also be set so that the context can be set up correctly. +For example, to use OpenGL 3.3 Core Profile: + +.. code-block:: cpp + + view.setHint(pugl::ViewHint::useCompatProfile, false); + view.setHint(pugl::ViewHint::contextVersionMajor, 3); + view.setHint(pugl::ViewHint::contextVersionMinor, 3); + +If you need to perform some setup using the OpenGL API, +there are two ways to do so. + +The OpenGL context is active when +:type:`CreateEvent` and +:type:`DestroyEvent` +events are dispatched, +so things like creating and destroying shaders and textures can be done then. + +Alternatively, if it is cumbersome to set up and tear down OpenGL in the event handler, +:func:`enterContext` and :func:`leaveContext` can be used to manually activate the OpenGL context during application setup. +Note, however, that unlike many other APIs, these functions must not be used for drawing. +It is only valid to use the OpenGL API for configuration in a manually entered context, +rendering will not work. +For example: + +.. code-block:: cpp + + pugl::enterContext(view); + myApp.setupOpenGL(); + pugl::leaveContext(view); + + while (!myApp.quit()) { + world.update(0.0); + } + + pugl::enterContext(view); + myApp.teardownOpenGL(); + pugl::leaveContext(view); + +Using Vulkan +^^^^^^^^^^^^ + +Vulkan-specific API is declared in the ``vulkan.hpp`` header. +This header includes Vulkan headers, +so if you are dynamically loading Vulkan at runtime, +you should define ``VK_NO_PROTOTYPES`` before including it. + +.. code-block:: cpp + + #define VK_NO_PROTOTYPES + + #include + +The Vulkan backend is provided by :func:`vulkanBackend()`: + +.. code-block:: cpp + + view.setBackend(pugl::vulkanBackend()); + +Unlike OpenGL, almost all Vulkan configuration is done using the Vulkan API directly. +Pugl only provides a portable mechanism to load the Vulkan library and get the functions used to load the rest of the Vulkan API. + +Loading Vulkan +^^^^^^^^^^^^^^ + +For maximum compatibility, +it is best to not link to Vulkan at compile-time, +but instead load the Vulkan API at run-time. +To do so, first create a :class:`VulkanLoader`: + +.. code-block:: cpp + + pugl::VulkanLoader loader{world}; + +The loader manages the dynamically loaded Vulkan library, +so it must be kept alive for as long as the application is using Vulkan. +You can get the function used to load Vulkan functions with :func:`VulkanLoader::getInstanceProcAddrFunc`: + +.. code-block:: cpp + + auto vkGetInstanceProcAddr = loader.getInstanceProcAddrFunc(); + +It is best to use this function to load everything at run time, +rather than link to the Vulkan library at run time. +You can, for example, pass this to get the ``vkCreateInstance`` function using this, +then use that to create your Vulkan instance. +In practice, you will want to use some loader or wrapper API since there are many Vulkan functions. + +It is not necessary to use :class:`VulkanLoader`, +you can, for example, use the ``DynamicLoader`` from ``vulkan.hpp`` in the Vulkan SDK instead. + +The details of using Vulkan are far beyond the scope of this documentation, +but Pugl provides a portable function, :func:`createSurface`, +to get the Vulkan surface for a view. +Assuming you have somehow created your ``VkInstance``, +you can get the surface for a view using :func:`createSurface`: + +.. code-block:: cpp + + VkSurfaceKHR* surface = nullptr; + puglCreateSurface(loader.getDeviceProcAddrFunc(), + view, + vulkanInstance, + nullptr, + &surface); + +Pugl does not provide API that uses ``vulkan.hpp`` to avoid the onerous dependency, +but if you are using it with exceptions and unique handles, +it is straightforward to wrap the surface handle yourself. + +Showing the View +---------------- + +Once the view is configured, it can be "realized" with :func:`View::realize`. +This creates a "real" system view, for example: + +.. code-block:: cpp + + pugl::Status status = view.realize(); + if (status != pugl::Status::success) { + std::cerr << "Error realizing view: " << pugl::strerror(status) << "\n"; + } + +Note that realizing a view can fail for many reasons, +so the return code should always be checked. +This is generally the case for any function that interacts with the window system. +Most functions also return a :enum:`Status`, +but these checks are omitted for brevity in the rest of this documentation. + +A realized view is not initially visible, +but can be shown with :func:`View::show`: + +.. code-block:: cpp + + view.show(); + +To create an initially visible view, +it is also possible to simply call :func:`View::show()` right away. +The view will be automatically realized if necessary. + +Handling Events +=============== + +Events are sent to a view when it has received user input, +must be drawn, or in other situations that may need to be handled such as resizing. + +Events are sent to the ``onEvent`` method that takes the matching event type. +The application must handle at least :type:`ConfigureEvent` +and :type:`ExposeEvent` to draw anything, +but there are many other :type:`event types `. + +For example, basic event handling for our above class might look something like: + +.. code-block:: cpp + + pugl::Status + MyView::onEvent(const pugl::ConfigureEvent& event) noexcept + { + return resize(event.width, event.height); + } + + pugl::Status + MyView::onEvent(const pugl::ExposeEvent& event) noexcept + { + return drawMyAwesomeInterface(event.x, event.y, event.width, event.height); + } + +Drawing +------- + +Note that Pugl uses a different drawing model than many libraries, +particularly those designed for game-style main loops like `SDL `_ and `GLFW `_. + +In that style of code, drawing is performed imperatively in the main loop, +but with Pugl, the application must draw only while handling an expose event. +This is because Pugl supports event-driven applications that only draw the damaged region when necessary, +and handles exposure internally to provide optimized and consistent behavior across platforms. + +Driving the Event Loop +====================== + +Pugl does not contain any threads or other event loop "magic". +For flexibility, the event loop is driven manually by repeatedly calling :func:`World::update`, +which processes events from the window system and dispatches them to views when necessary. + +The exact use of :func:`World::update` depends on the application. +Plugins typically call it with a ``timeout`` of 0 in a callback driven by the host. +This avoids blocking the main loop, +since other plugins and the host itself need to run as well. + +A program can use whatever timeout is appropriate: +event-driven applications may wait forever by using a ``timeout`` of -1, +while those that draw continuously may use a significant fraction of the frame period +(with enough time left over to render). + +Redrawing +--------- + +Occasional redrawing can be requested by calling :func:`View::postRedisplay` or :func:`View::postRedisplayRect`. +After these are called, +a :type:`ExposeEvent` will be dispatched on the next call to :func:`World::update`. +Note, however, that this will not wake up a blocked :func:`World::update` call on MacOS +(which does not handle drawing via events). + +For continuous redrawing, +call :func:`View::postRedisplay` while handling a :type:`UpdateEvent`. +This event is sent just before views are redrawn, +so it can be used as a hook to expand the update region right before the view is exposed. +Anything else that needs to be done every frame can be handled similarly. + +.. _pkg-config: https://www.freedesktop.org/wiki/Software/pkg-config/ + +.. rubric:: Footnotes + +.. [#f1] MacOS has a strong distinction between + `views `_, + which may be nested, and + `windows `_, + which may not. + On Windows and X11, everything is a nestable window, + but top-level windows are configured differently. diff --git a/doc/cpp/wscript b/doc/cpp/wscript new file mode 100644 index 0000000..a7aefc1 --- /dev/null +++ b/doc/cpp/wscript @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +def build(bld): + dox_to_sphinx = bld.path.find_node("../../scripts/dox_to_sphinx.py") + index_xml = bld.path.get_bld().make_node("xml/index.xml") + + files = [ + ("../../resources/pugl.svg", "sphinx/_static/pugl.svg"), + ("../_static/custom.css", "sphinx/_static/custom.css"), + ("../_templates/about.html", "sphinx/_templates/about.html"), + ("../deployment.rst", "sphinx/deployment.rst"), + ("../pugl.rst", "sphinx/pugl.rst"), + ("c-reference.rst", "sphinx/c-reference.rst"), + ("cpp-reference.rst", "sphinx/cpp-reference.rst"), + ("index.rst", "sphinx/index.rst"), + ("overview.rst", "sphinx/overview.rst"), + ] + + # Run Doxygen to generate XML documentation + bld(features="doxygen", doxyfile="Doxyfile") + + # Substitute variables to make Sphinx configuration file + bld(features="subst", + source="../conf.py.in", + target="sphinx/conf.py", + PUGL_VERSION=bld.env.PUGL_VERSION) + + # Copy static documentation files to Sphinx build directory + for f in files: + bld(features="subst", is_copy=True, source=f[0], target=f[1]) + + # Generate Sphinx markup from Doxygen XML + bld.add_group() + bld(rule="${PYTHON} " + dox_to_sphinx.abspath() + " -l cpp -f ${SRC} ${TGT}", + source=index_xml, + target="sphinx/api/") + + # Run Sphinx to generate HTML documentation + doc_dir = bld.env.DOCDIR + "/pugl-%s/" % bld.env.PUGL_MAJOR_VERSION + bld(features="sphinx", + sphinx_source=bld.path.get_bld().make_node("sphinx"), + sphinx_output_format="singlehtml", + sphinx_options=["-E", "-q"], + install_path=doc_dir + "cpp/singlehtml/") diff --git a/doc/deployment.rst b/doc/deployment.rst new file mode 100644 index 0000000..ffbeae9 --- /dev/null +++ b/doc/deployment.rst @@ -0,0 +1,23 @@ +########## +Using Pugl +########## + +Pugl is designed for flexible deployment, +so the exact method of building against it depends on your approach. + +When targeting systems with pkg-config_, +packages are provided that link against the core platform library and the desired backend, +along with any backend dependencies: + +- ``pugl-cairo-0`` +- ``pugl-gl-0`` +- ``pugl-vulkan-0`` + +Depending on one of these packages should be all that is necessary to use Pugl, +but details on the individual libraries that are installed are available in the README. + +If you are instead including the source directly in your project, +the structure is quite simple and hopefully obvious. +It is only necessary to copy the platform and backend implementations that you need. + +.. _pkg-config: https://www.freedesktop.org/wiki/Software/pkg-config/ diff --git a/doc/footer.html b/doc/footer.html deleted file mode 100644 index 0dc6919..0000000 --- a/doc/footer.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - diff --git a/doc/header.html b/doc/header.html deleted file mode 100644 index 54c25b0..0000000 --- a/doc/header.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - $projectname: $title - $title - - $extrastylesheet - - -
- - -
- -
- - - - - diff --git a/doc/layout.xml b/doc/layout.xml deleted file mode 100644 index 2995c0e..0000000 --- a/doc/layout.xml +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/mainpage.md b/doc/mainpage.md index c04bf9e..92f7409 100644 --- a/doc/mainpage.md +++ b/doc/mainpage.md @@ -1,23 +1,29 @@ -This is the API documentation for Pugl. -This page refers to the [C API](@ref pugl_c), -there is also a [C++ API](@ref pugl_cxx) in the `pugl` namespace. +This is the documentation for Pugl, a minimal API for writing GUIs. -The Pugl API revolves around two main objects: -the [World](@ref world) and the [View](@ref view). +## Reference + +Pugl is implemented in C, but also provides a header-only C++ API wrapper. + + * [C API reference](@ref pugl) + * [C++ API reference](@ref puglxx) + +## Overview + +The Pugl API revolves around two main objects: the World and the View. An application creates a single world to manage top-level state, then creates one or more views to display. -## World +### World -The [World](@ref world) contains all top-level state, +The [World](@ref PuglWorld) contains all top-level state, and manages views and the event loop. A world must be [created](@ref puglNewWorld) before any views, and it must outlive all views. -## View +### View -A [View](@ref view) is a drawable region that receives events. +A [View](@ref PuglView) is a drawable region that receives events. Creating a visible view is a multi-step process. When a new view is [created](@ref puglNewView), @@ -28,27 +34,25 @@ and be configured by [setting hints](@ref puglSetViewHint) and optionally [adjusting the frame](@ref frame). The [Backend](@ref PuglBackend) controls drawing for a view. -Pugl includes [Cairo](@ref cairo) and [OpenGL](@ref gl) backends, -as well as a [stub](@ref stub) backend that creates a native window with no drawing context. - +Pugl includes [Cairo](@ref cairo), [OpenGL](@ref gl), and [Vulkan](@ref vulkan) backends, +as well as a [stub](@ref stub) backend that creates a native window with no portable drawing context. Once the view is configured, -it can be [realized](@ref puglRealize) and [shown](@ref puglShowWindow). +it can be [realized](@ref puglRealize) and [shown](@ref puglShow). By default a view will correspond to a top-level system window. To create a view within another window, it must have a [parent window set](@ref puglSetParentWindow) before being created. +### Events -## Events - -[Events](@ref events) are sent to a view when it has received user input or must be drawn. +[Events](@ref PuglEvent) are sent to a view when it has received user input or must be drawn. Events are handled by the [event handler](@ref PuglEventFunc) set during initialisation. This function is called whenever something happens that the view must respond to. This includes user interaction like mouse and keyboard input, and system events like window resizing and exposure. -## Event Loop +### Event Loop The event loop is driven by repeatedly calling #puglUpdate which processes events from the window system, and dispatches them to views when necessary. @@ -68,6 +72,6 @@ For continuous redrawing, call #puglPostRedisplay when a #PUGL_UPDATE event is r This event is sent before views are redrawn, so can be used as a hook to expand the update region right before the view is exposed. -## Error Handling +### Error Handling -Most functions return a [Status](@ref status) which should be checked to detect failure. +Most functions return a [Status](@ref PuglStatus) which should be checked to detect failure. diff --git a/doc/pugl.rst b/doc/pugl.rst new file mode 100644 index 0000000..c48021b --- /dev/null +++ b/doc/pugl.rst @@ -0,0 +1,26 @@ +#### +Pugl +#### + +Pugl is an API for writing portable and embeddable GUIs. +Pugl is not a toolkit or framework, +but a minimal portability layer that sets up a drawing context and delivers events. + +Compared to other libraries, +Pugl is particularly suitable for use in plugins or other loadable modules. +There is no implicit context or static data in the library, +so it may be statically linked and used multiple times in the same process. + +Pugl has a modular design that separates the core library from graphics backends. +The core library is graphics agnostic, +it implements platform support and depends only on standard system libraries. +MacOS, Windows, and X11 are currently supported as platforms. + +Graphics backends are separate so that applications only depend on the API that they use. +Pugl includes graphics backends for Cairo_, OpenGL_, and Vulkan_. +It is also possible to use some other graphics API by implementing a custom backend, +or simply accessing the native platform handle for a window. + +.. _Cairo: https://www.cairographics.org/ +.. _OpenGL: https://www.opengl.org/ +.. _Vulkan: https://www.khronos.org/vulkan/ diff --git a/doc/reference.doxygen.in b/doc/reference.doxygen.in deleted file mode 100644 index 4e91ca2..0000000 --- a/doc/reference.doxygen.in +++ /dev/null @@ -1,2462 +0,0 @@ -# Doxyfile 1.8.15 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the configuration -# file that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# https://www.gnu.org/software/libiconv/ for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = Pugl - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = @PUGL_VERSION@ - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "A minimal portable API for embeddable GUIs" - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = . - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = NO - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = NO - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice -# sources only. Doxygen will then generate output that is more tailored for that -# language. For instance, namespaces will be presented as modules, types will be -# separated into more groups, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_SLICE = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: -# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser -# tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is -# Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up -# to that level are automatically included in the table of contents, even if -# they do not have an id attribute. -# Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -TOC_INCLUDE_HEADINGS = 0 - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = YES - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = YES - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = YES - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = NO - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = YES - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = YES - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = YES - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = NO - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = NO - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = NO - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = @PUGL_SRCDIR@/doc/layout.xml - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = NO - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = @PUGL_SRCDIR@/pugl/ \ - @PUGL_SRCDIR@/doc/mainpage.md - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. - -FILE_PATTERNS = *.h *.hpp - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = *.c - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = @PUGL_SRCDIR@/doc/mainpage.md - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# entity all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = NO - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see https://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = NO - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = @PUGL_SRCDIR@/doc/header.html - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = @PUGL_SRCDIR@/doc/footer.html - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = @PUGL_SRCDIR@/doc/style.css - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# https://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 120 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 32 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML -# documentation will contain a main index with vertical navigation menus that -# are dynamically created via Javascript. If disabled, the navigation index will -# consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have Javascript, -# like the Qt help browser. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_MENUS = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy -# genXcode/_index.html for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 0 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /