File indexing completed on 2024-05-12 04:44:32

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 // This file contains the following documentation:
0005 // – All the @page documentation. Putting all @page documentation in this
0006 //   single file allows that they show up in the documentation in
0007 //   alphabetical order.
0008 // – The namespace documentation
0009 
0010 /** @page build Build instructions and requirements
0011  *
0012  * Build-time dependencies:
0013  * - LittleCMS 2 (minimum version: 2.0)
0014  * - Qt 5 (minimum version: 5.15) <!-- Qt 5.15 has an API that is close
0015  *   to Qt 6. It introduces some new functions we are using to avoid
0016  *   deprecated older functions. --> or Qt 6 (minimum version: 6.0.0).
0017      Components: Core, Gui, Widgets, DBus, Concurrent, Test, Svg.
0018  * - CMake
0019  * - ECM (Extra CMake Modules from KDE)
0020  * - C++17
0021  * - Both, the input character set and the execution character set, have
0022  *   to be UTF8. (See @ref compilercharacterset for more details.)
0023  * <!--
0024  *      Qt 5.6 (which is the minimum Qt version required
0025  *      by this library) only requires C++03. Only starting
0026  *      with Qt 5.7, Qt itself requires C++11. Source:
0027  *      https://doc.qt.io/qt-5.9/cmake-manual.html#using-qt-5-with-cmake-older-than-3-1-0
0028  *
0029  *      Qt 6 requires minimum C++17, as
0030  *      https://doc-snapshots.qt.io/qt6-dev/cmake-get-started.html
0031  *      explains.
0032  *
0033  *      Our library code uses C++11 features, for example “constexpr”.
0034  *
0035  *      In the CMakeLists.txt file, we set -std=c++17 and we set
0036  *      also -Wpedantic and -pedantic-errors to enforce it. That is
0037  *      a useful option for this library if we decide to make it Qt-6-only.
0038  *      But it is even be useful if we support Qt 5, so we have future-proof
0039  *      requirements that we do not have to raise soon, and that are a
0040  *      good base for LTS.
0041  * -->
0042  * - Optional: There is also a LittleCMS plugin called
0043  *   <em>fast_float plug-in</em> that you can include into the
0044  *   source code of your application and load it in your main function
0045  *   before using this library. This can make color management faster.
0046  *   (Note that this plugin has a different license than LittleCMS itself.)
0047  *
0048  * Additional mandatory run-time dependencies:
0049  * - QSvgIconEnginePlugin. Available plugins are loaded
0050  *   automatically by Qt. Therefore, just make sure that this plugin is
0051  *   present. On Linux, it seems possible to enforce this by linking
0052  *   dynamically to the plugin itself, if you want to. This forces Linux
0053  *   package managers to produce packages of your application that depend
0054  *   not only on Qt base, but also on the SVG plugin. A typical file name of
0055  *   the plugin is <tt>plugins/iconengines/libqsvgicon.so</tt>.
0056  *
0057  * Please make sure that you comply with the licences of used libraries.
0058  *
0059  * To prepare the build, run cmake. We provide plenty of CMake options
0060  * that control the build type (shared/dynamic vs. static), IPO/LPO and
0061  * much more. The options are self-documenting. When you run CMake,
0062  * the options are listed with their values and a description of them.
0063  *
0064  * Then, to build and install the library:
0065  * @code{.unparsed}
0066  * make && sudo make install
0067  * @endcode
0068  *
0069  * To do unit testing:
0070  * @code{.unparsed}
0071  * make build_test test
0072  * @endcode */
0073 
0074 /** @internal
0075  *
0076  * @page codingstyle Coding style
0077  *
0078  * Always document your code.
0079  *
0080  * @section codingstylecpp C++
0081  *
0082  * - Provide unit tests for your code.
0083  * - If working with children within Qt’s object hierarchy, allocate on the
0084  *   heap and use raw pointers or guarded pointers (`QPointer`). If not,
0085  *   allocate on the stack or use smart pointers. Prefer Qt’s smart pointers
0086  *   over the <tt>std</tt> smart pointers of C++.
0087  * - Use KDE’s
0088  *   <a href="https://community.kde.org/Policies/Frameworks_Coding_Style">
0089  *   Frameworks Coding Style</a>. This can be done automatically with
0090  *   clang-format.
0091  * - Comments within the code should have this form: <tt>// comment</tt>
0092  *   <br/> This allows to comment out quickly large parts of the code for
0093  *   testing purposes.
0094  * - Comments for Doxygen should have this form: <tt>/⁠** Comment *⁠/</tt>
0095  *
0096  * @section codingstylecmake CMake
0097  *
0098  * @subsection codingstylecmakeusefuldocumentation Useful documentation
0099  *
0100  * - <a href="https://preshing.com/20170522/learn-cmakes-scripting-language-in-15-minutes/">
0101  *   Introduction to the CMake script language</a>
0102  * - <a href="https://github.com/onqtam/awesome-cmake">
0103  *   Curated list of awesome CMake scripts, modules, examples and others</a>
0104  * - <a href="https://llvm.org/docs/CMakePrimer.html">General introduction
0105  *   into CMake (both, the script language and the commands)</a>
0106  *
0107  * @subsection codingstylecmakemodern Use “Modern CMake”
0108  *
0109  * Use <em>Modern CMake</em>: Avoid global settings like
0110  * <tt>include_directories()</tt>. Use target-based commands like
0111  * <tt>target_include_directories()</tt> instead. Use
0112  * <tt>target_link_libraries()</tt> to pull in dependencies, which gives you
0113  * automatically the correct include directories, compile options etc.
0114  * When using <tt>target_link_libraries()</tt>, always specify
0115  * <tt>PUBLIC</tt> or <tt>PRIVATE</tt> or <tt>INTERFACE</tt> explicitly.
0116  *
0117  * @subsection codingstylecmakeindent Indent
0118  *
0119  * Use 4 spaces for indenting. Do not use tabs.
0120  *
0121  * @subsection codingstylecmakequotationmarks Quotation marks
0122  *
0123  * Use quotation marks when you want to represent a string.
0124  * Do not use quotation marks when you mean a keyword. Example:
0125  *
0126  * @code{.unparsed}
0127  * set(myvar "foo")
0128  * @endcode
0129  *
0130  * Particularly, always quote strings within control structures:
0131  *
0132  * @code{.unparsed}
0133  * if("${myvar}" STREQUAL "bar")
0134  * @endcode
0135  *
0136  * @subsection codingstylecmakeboolean Boolean
0137  *
0138  * CMake allows various representations of boolean. Use only the forms
0139  * <tt>TRUE</tt> and <tt>FALSE</tt>. Do not quote them.
0140  *
0141  * @subsection codingstylevariablecheck Check if a variable exists
0142  *
0143  * Check if a variable exists like this:
0144  *
0145  * @code{.unparsed}
0146  * if(DEFINED varname)
0147  * @endcode
0148  *
0149  * @subsection codingstylecmakenaming Naming
0150  *
0151  * Functions and macros:
0152  *
0153  * @code{.unparsed}
0154  * lower_case()
0155  * @endcode
0156  *
0157  * Control structures: <tt>lower_case()</tt>, with empty <tt>else()</tt>,
0158  * <tt>endif()</tt>, <tt>endfunction()</tt>…
0159  *
0160  * Operators/keywords/directives/extra options: <tt>UPPER_CASE</tt> without
0161  * quotes. Examples:
0162  *
0163  * @code{.unparsed}
0164  * if(condition STREQUAL "")
0165  * @endcode
0166  *
0167  * @code{.unparsed}
0168  * do_something(... USE_THIS)
0169  * @endcode
0170  *
0171  * @code{.unparsed}
0172  * file(COPY ...)
0173  * @endcode
0174  *
0175  * @subsection codingstyleparenthesis Parenthesis
0176  *
0177  * Multi-line calls have trailing parenthesis on the same line as
0178  * last parameter, not on separate line:
0179  *
0180  * @code{.unparsed}
0181  * set(my_variable
0182  *     "value1"
0183  *     "value2"
0184  *     "value3)
0185  * @endcode
0186  *
0187  * @subsection codingstyleorder Order
0188  *
0189  * Source and header lists should be ordered alphabetically,
0190  * subdirectories last, preferably separated by a single empty line.
0191  *
0192  * @subsection codingstylelinelength Line length
0193  *
0194  * Keep the length of the line below 80 characters when possible.
0195  * No trailing whitespace.
0196  *
0197  * @subsection codingstyledirectories Directories
0198  *
0199  * A directory path may not have a trailing <tt>/</tt>. This is to avoid
0200  * duplicates like <tt>//</tt> when composing paths:
0201  *
0202  * @code{.unparsed}
0203  * set(my_path "/usr/bin/") # BAD
0204  * set(my_path "/usr/bin") # GOOD
0205  * set(my_file "${my_path}/my_file")
0206  * @endcode
0207  *
0208  * @subsection codingstylelists Lists
0209  *
0210  * Declaring an empty list:
0211  *
0212  * @code{.unparsed}
0213  * set(mylist)
0214  * @endcode
0215  *
0216  * Declaring and initializing a list at the same time:
0217  *
0218  * @code{.unparsed}
0219  * set(mylist
0220  *     "first item"
0221  *     "second item"
0222  *     "third item")
0223  * @endcode
0224  *
0225  * Append to a list:
0226  *
0227  * @code{.unparsed}
0228  * list(APPEND mylist "last item")
0229  * @endcode
0230  *
0231  * @subsection codingstyleprojectname ${PROJECT_NAME}
0232  *
0233  * Use <tt>${PROJECT_NAME}</tt> for global variables, targets and labels
0234  * instead of repeating the project name manually or using fixed names:
0235  *
0236  * @code{.unparsed}
0237  * add_executable(${PROJECT_NAME} …)
0238  * @endcode */
0239 
0240 /** @page compilercharacterset Compiler character sets
0241  *
0242  * @section compilercharacterset_ Compiler character sets
0243  *
0244  * Compilers have three different character sets:
0245  * - Input character set (the character set of the source code)
0246  * - Narrow execution character set
0247  *   (for <tt>char</tt> and for string literals without prefix)
0248  * - Wide execution character set
0249  *   (for <tt>wchar_t</tt> and for string literals with <tt>L</tt> prefix)
0250  *
0251  * @subsection inputcharacterset Input character set
0252  *
0253  * This source code of this library is encoded in UTF8. Therefore, your
0254  * compiler must treat is also as UTF-8.
0255  *
0256  * Why are we using UTF-8 instead of ASCII?
0257  * - UTF-8 is more complete than ASCII. ASCII does not even provide basic
0258  *   typographic symbols like en-dash, em-dash or non-breaking space
0259  *   characters or quotes.
0260  * - Unicode exists since 1991, UTF-8 since 1993. It’s time to get rid of
0261  *   the insufficient ASCII character. It’s time to use Unicode.
0262  * - We use non-ASCII characters for (typographically
0263  *   correct) Doxygen documentation and partially also for non-Doxygen
0264  *   source code comments. It would be quite annoying to use HTML
0265  *   entities for each non-ASCII character in the Doxygen documentation;
0266  *   and it would be pointless to do it for non-Doxygen source code
0267  *   comments.
0268  * - <tt>i18n()</tt> and <tt>ki18n()</tt> and <tt>tr()</tt> require both,
0269  *   the source file and <tt>char*</tt> to be encoded in UTF-8; no other
0270  *   encodings are supported. (Only ASCII would be UTF-8 compatible,
0271  *   but in practice this encoding is not supported, but only 8859-Latin
0272  *   encodings, which allow code points higher than 127, which risks to
0273  *   introduce incompatibilities. Therefore, this would not be a good
0274  *   option.)
0275  * - The C++ identifiers of library symbols are however (currently)
0276  *   ASCII-only.
0277  *
0278  * So we use a <tt>static_assert</tt> statement to control this.
0279  *
0280  * @subsection narowexecutioncharacterset Narrow execution character set
0281  *
0282  * Why are we using UTF-8 as narrow execution character set?
0283  * - <tt>i18n()</tt> and <tt>ki18n()</tt> and <tt>tr()</tt> require both,
0284  *   the source file and <tt>char*</tt> to be encoded in UTF-8; no other
0285  *   encodings are supported.
0286  * - Implicit conversion from <tt>char*</tt> to <tt>QString</tt> assumes
0287  *   that <tt>char*</tt> is UTF-8 encoded. Thus we disable this implicit
0288  *   conversion in <tt>CMakeLists.txt</tt>, it’s wise to stay compatible.
0289  *
0290  * Therefore, a static assert controls that really UTF-8 is used
0291  * as narrow execution character set.
0292  *
0293  * @subsection wideexecutioncharacterset Wide execution character set
0294  *
0295  * We do not use actively the wide execution character set. There is
0296  * a usage when communicating with LittleCMS, but there we depend anyway
0297  * from LittleCMS. Therefore, currently, no static assert forces a specific
0298  * wide execution character set.
0299  *
0300  * @internal
0301  *
0302  * @note The static asserts that enforce the character sets are located
0303  * in @ref staticasserts.cpp. */
0304 
0305 /** @internal
0306  *
0307  * @page datatypes Data types
0308  *
0309  * The library uses in general <tt>int</tt> for integer values, because
0310  * <tt>QSize()</tt> and <tt>QPoint()</tt> also do. As the library relies
0311  * heavily on the usage of <tt>QSize()</tt> and <tt>QPoint()</tt>, this
0312  * seems reasonable.
0313  *
0314  * For the same reason, it uses generally <tt>qreal</tt>
0315  * for floating point values, because <tt>QPointF()</tt> also does.
0316  *
0317  * Output colors that are shown on the screen, are usually 8-bit-per-channel
0318  * colors. For internal transformation, usually <tt>qreal</tt>
0319  * is used for each channel, giving a better precision and reducing rounding
0320  * errors. */
0321 
0322 /** @internal
0323  *
0324  * @page generaltodolist General TODO list
0325  *
0326  * This is a TODO list that contains general ideas or issues of this
0327  * library.
0328  *
0329  * @todo Use words as hints for color ranges? Muted/dull colors have a low
0330  * chroma value. The dark ones (getrübte/gebrochene Farben) are created by
0331  * adding black (and possibly a bit of white) and include warm tones (the
0332  * browns) and cool tones (the olives). The light ones are called Pastel
0333  * colors and are created by adding white (and possibly a bit of
0334  * black) and include warm tones (like baby pink) and cool
0335  * tones (like baby blue). Warm colors are located at a color angle of
0336  * about 45°, cool colors at about 225°. Could we mark this in the diagrams?
0337  * Cold and warm could be marked by a text outside the color wheel at the
0338  * given position. The other ones seem to be more complicated: These specific
0339  * color terms do not have a translation in all languages. (For “muted colors”,
0340  * there is no good German translation, and for “getrübte Farben”, there is
0341  * no good English translation.
0342  *
0343  * @todo A design question: Following KDE’s HIG, if the command requires
0344  * additional user interaction to complete, at the end its label there
0345  * should be an elipsis sfs (…). Currently, this only seems to apply
0346  * to @ref PerceptualColor::ColorDialogPrivate::m_screenColorPickerButton.
0347  *
0348  * @todo https://invent.kde.org/plasma/kdeplasma-addons/-/merge_requests/249
0349  * allows the user to drag and drop an image file. The image’s average color
0350  * is calculated and set as current color of Plasma’s color picker widget.
0351  * Furthermore, it seems that Plasma’s color picker widget also accepts
0352  * color codes for drag-and-drop. (Which ones? Maybe the #128945 style?)
0353  * Would this make sense also for our library?
0354  *
0355  * @todo ITUR profile: Minimum widget size must be smaller! On high sizes, the
0356  * inner focus indicator of color wheel too narrow to hue circle.
0357  * On RGB 255 0 0 no value indicator is visible. The high-chroma values
0358  * are empty in the diagram!
0359  *
0360  * @todo Touch friendly: @ref PerceptualColor::ColorPatch,
0361  * @ref PerceptualColor::GradientSlider etc. at least
0362  * as thick as (normal) buttons. Qt6 replaces QTouchDevice by
0363  * QInputDevice::devices()…
0364  *
0365  * @todo For all diagram images: No abort during first interlacing pass. (See
0366  * @ref PerceptualColor::AsyncImageProvider for details.)
0367  *
0368  * @todo All scripts (both, local and CI scripts) should break and stop
0369  * on every error. When implementing this, be beware of side effects
0370  * (some local scripts are also called from the CI and so on…).
0371  *
0372  * @todo Review @ref PerceptualColor::RgbColorSpace. And change
0373  * it in order to allow support for Oklab. And maybe Googles
0374  * <a href="https://github.com/material-foundation/material-color-utilities">
0375  * HTC</a>.
0376  *
0377  * @todo A design question: In the chroma-lightness diagram, the color
0378  * wheel is a slider and reacts as such. However, in the chroma-hue-diagram,
0379  * the same color wheel is just decoration (for orientation). Isn’t this
0380  * different behaviour of two visually identical elements confusing?
0381  *
0382  * @todo A design question: Should we use
0383  * <a href="https://doc.qt.io/qt-6/qt.html#CursorShape-enum">
0384  * <tt>Qt::CrossCursor</tt></a> for two-dimensional selections like
0385  * @ref PerceptualColor::ChromaHueDiagram? And should we use
0386  * <a href="https://doc.qt.io/qt-6/qt.html#CursorShape-enum"><tt>
0387  * Qt::UpArrowCursor</tt></a> for one-dimensional selections like
0388  * @ref PerceptualColor::GradientSlider?
0389  *
0390  * @todo Remove things form the public API, leaving only the absolutely
0391  * minimal API that is required by the user.
0392  *
0393  * @todo Avoid “final” in the public API (or even altogether?). Implement
0394  * a codecheck for this.
0395  *
0396  * @todo <a href="https://valgrind.org/docs/manual/quick-start.html"> Test with
0397  * valgrind.org</a>
0398  *
0399  * @todo Most widgets of this library allocate in each paint event a new
0400  * buffer to paint on, before painting on the widget. This is also done
0401  * because only <tt>QImage</tt> guarantees the same result on all platforms,
0402  * while <tt>QPixmap</tt> is platform-dependent and Qt does not guarantee that
0403  * for example <tt>QPainter::Antialiasing</tt> is available on all platforms.
0404  * However, not using a buffer would save memory! Can we know if the current
0405  * platform supports <tt>QPainter::Antialiasing</tt> and buffer only if
0406  * necessary? Or could we at least instantiate only one single buffer per
0407  * application, that is than shared between all the widgets of our library?
0408  * This buffer would never be freed, so it will always occupy memory. But
0409  * this avoids the time-consuming memory allocations at each paint event!
0410  *
0411  * @todo Use <tt>QCache</tt> where is makes sense. Maybe
0412  * @ref PerceptualColor::RgbColorSpace::reduceCielchD50ChromaToFitIntoGamut() or
0413  * @ref PerceptualColor::RgbColorSpace::isCielchD50InGamut() or
0414  * @ref PerceptualColor::RgbColorSpace::isCielabD50InGamut() or
0415  * @ref PerceptualColor::ChromaLightnessDiagramPrivate::nearestInGamutColorByAdjustingChromaLightness(().
0416  *
0417  * @todo Switch AbstractDiagram::handleOutlineThickness() and
0418  * handleRadius() and spaceForFocusIndicator() to use PM_DefaultFrameWidth.
0419  * (PM_DefaultFrameWidth seems to be used yet in ColorPatch.)
0420  *
0421  * @todo QColor is ambiguous: It allows different types of color system,
0422  * or even various versions of the same color system at different
0423  * precisions (RGB). This makes it difficult to communicate in the API
0424  * which is the type of color (model) it contains. Therefore, we should
0425  * eliminate all its usage within this library (except where it is necessary
0426  * for API compatibility with Qt).
0427  *
0428  * @todo If using the Motif style, the @ref PerceptualColor::ChromaHueDiagram
0429  * widget, which has circular look-and-feel, has a rectangular focus
0430  * indicator corresponding the rectangular widget geometry, which looks
0431  * quite ugly. On the other hand, @ref PerceptualColor::WheelColorPicker
0432  * has also circular  look-and-feel, but no rectangular focus indicator
0433  * corresponding the rectangular widget geometry, which looks better.
0434  * Why doesn’t @ref PerceptualColor::ChromaHueDiagram also behave
0435  * like @ref PerceptualColor::WheelColorPicker? And
0436  * how does @ref PerceptualColor::ColorWheel behave?
0437  *
0438  * @todo Idea: Provide QColorWidget (like QColorDialog, but inheriting
0439  * from QWidget, and no buttons). Does this make sense?
0440  *
0441  * @todo Use implicit data sharing in @ref PerceptualColor::RgbColorSpace
0442  * instead of <tt>QSharedPointer\< @ref PerceptualColor::RgbColorSpace \></tt>.
0443  * But: Wouldn’t this require to make the declaration
0444  * of @ref PerceptualColor::RgbColorSpace, which was secret until today,
0445  * public? If so, this would not be good…
0446  *
0447  * @todo Dual-Licence with Apache2 and/or Boost licence?
0448  *
0449  * @todo Reduce number of exported symbols.
0450  *
0451  * @todo Rename main.cpp.
0452  *
0453  * @todo Currently, we consider that a mouse clicks click a pixel, but mean
0454  * the coordinate point in the middle of this pixel. This seems an approach
0455  * that other widgets (including Qt itself) do not use. And maybe is meant also
0456  * the coordinate at the top of the mouse cursor, so no offset by (0.5, 0.5)
0457  * would be necessary. This would give better results (at least on LTR
0458  * mouse cursors, but what's about crosshair cursors and RTL cursors?)
0459  *
0460  * @todo We do some hacks to get circle-like (instead of rectangular)
0461  * feeling for our circular widgets, which is not perfect when talking
0462  * about mouse events. It seems that QWidget::setMask() offers an
0463  * alternative, restricting mouse events (and painting) to a given
0464  * mask. Does this actually work also for mouse focus management?
0465  * If so: Has it performance penalties? If not, we should probably use
0466  * it! And document that those widgets are circular widgets and from
0467  * a user perspective behave like circular widgets (both paint event
0468  * and mouse cursor reactions/usage feeling), though from an application
0469  * programmer (that uses this library) perspective, they are of course
0470  * rectangular in the layout system. And: Post the results on
0471  * <a href="https://forum.qt.io/topic/118547/accept-reject-focus-coming-by-mouse-click-based-on-coordinates">
0472  * this Qt Forum thread</a>.
0473  *
0474  * @todo Support more of Qt Style Sheets, for example allow
0475  * customizing the neutral-gray background of diagrams? If
0476  * so, @ref PerceptualColor::drawQWidgetStyleSheetAware()
0477  * is available. Otherwise, remove the currently not used
0478  * @ref PerceptualColor::drawQWidgetStyleSheetAware() from
0479  * this library.
0480  *
0481  * @todo Unit tests for endianess. Maybe QtEndian can help…
0482  *
0483  * @todo General library properties:
0484  * - test cross-platform support and different byte-orders
0485  * - Could we integrate more with QStyle? Apparently
0486  *   <a href="https://api.kde.org/frameworks/frameworkintegration/html/classKStyle.html">
0487  *   KStyle</a> is a QCommonStyle-based class that provides
0488  *   support for QString-based query for custom style hints,
0489  *   control elements and sub elements. There is also
0490  *   <a href="https://api.kde.org/frameworks/kwidgetsaddons/html/namespaceKStyleExtensions.html">
0491  *   KStyleExtensions</a> that allows apparently custom widgets to query
0492  *   for these QString-based custom support, which allows to make the same
0493  *   query independently of the actual style, without the need to hard-code
0494  *   individual custom enum values for QStyle::ControlElement (and similar
0495  *   enum) for each individual style. KStyleExtensions works for all
0496  *   styles, also for these that are <em>not</em> subclasses of
0497  *   <tt>KStyle</tt>. It reports if a given query is supported or not
0498  *   by the underlying style. However, even Breeze, KDE’s default style,
0499  *   seems not to inherit from KStyle, so the question is if KStyle is
0500  *   not rather deprecated yet. An alternative would be if a style
0501  *   has special functions just for PerceptualColor rendering, like
0502  *   <tt>renderColorWheel</tt>. Than, we could cast the current QStyle
0503  *   of the application to this style (if the actual current
0504  *   style <em>is</em> this style), and call these functions. Big
0505  *   disadvantage: We would have to <em>link</em> against all styles
0506  *   that we want to support, which makes our library <em>depend</em>
0507  *   on them, which is not reasonable.
0508  * - More work on accessibility. [This includes to work well with bigger
0509  *   fonts. Should then the gradient be thicker and the marker
0510  *   thicker? setAccessibleName().] The application Accerciser provides
0511  *   inspection possibilities.
0512  *
0513  * @todo From KDE’s binary compatibility info page: In order to make a class
0514  * to extend in the future you should follow these rules:
0515  * - add non-inline virtual destructor even if the body is empty.
0516  * - re-implement event in QObject-derived classes, even if the body for
0517  *   the function is just calling the base class' implementation. This is
0518  *   specifically to avoid problems caused by adding a reimplemented virtual
0519  *   function as discussed below.
0520  *
0521  * @todo Following the recommendation of the C++ core guidelines, all
0522  * destructors should be noexcept.
0523  *
0524  * @todo Make genereatescreenshots and the unit tests run on hardware
0525  * without graphic card. This would be good for Continuous Integration.
0526  * The XVFB Virtual framebuffer (https://de.m.wikipedia.org/wiki/Xvfb)
0527  * can do this for X apps. Also, it is possible to start X apps on
0528  * terminal without a window manager, see
0529  * https://linuxconfig.org/how-to-run-x-applications-without-a-desktop-or-a-wm
0530  * but I suppose an X server is still required? There seem to exist also
0531  * possibilities for Wayland
0532  * https://unix.stackexchange.com/questions/653672/virtual-wayland-display-server-possible
0533  * Also, there seems to be a Qt Platform Abstraction called “minimal”
0534  * (https://doc.qt.io/qt-6/qpa.html) for testing purposes. Elsewhere,
0535  * if I remember correctly, it was described as useful for testing without X.
0536  *
0537  * @todo The missing 3rd diagram (hue-lightness? But: Impossible to model
0538  * the circular behaviour of the LCH color space: It cannot be a cut through
0539  * the gamut body, but has to be a curve within the gamut body – not so
0540  * nice. And: The diagram width has to change with the selected hue if we want
0541  * to have correct scaling between x axis and y axis…
0542  *
0543  * @todo In https://phabricator.kde.org/T12359 is recommended to provide
0544  * RESET statements for all properties for better compatibility with QML.
0545  * As we provide widgets, this should not be too important. Are there also
0546  * good arguments for widgets to provide RESET?
0547  *
0548  * @todo Provide an init() function that calls qRegisterMetaType() for
0549  * all our types?
0550  *
0551  * @todo We prevent division by 0 in
0552  * @ref PerceptualColor::ChromaLightnessDiagramPrivate::fromWidgetPixelPositionToColor().
0553  * We should make sure this happens also in the other diagram widgets!
0554  *
0555  * @todo Add a @ref PerceptualColor::ConstPropagatingUniquePointer to
0556  * all classes, including the non-pimpl classes, to allow for later
0557  * enhancements.
0558  *
0559  * @todo Remove setDevicePixelRatioF from all *Image classes. (It is
0560  * confusing, and at the same time there is no real need/benefit.)
0561  * Complete list: @ref PerceptualColor::ChromaHueImageParameters,
0562  * @ref PerceptualColor::ColorWheelImage,
0563  * @ref PerceptualColor::GradientImageParameters.
0564  *
0565  * @todo Test also on Windows. (Does it work well with VisualStudio?)
0566  *
0567  * @todo Test also Big-Endian compatibility using s390x Linux via Qemu?
0568  * KDE Invent does not support this out-of-the-box, but with a custom
0569  * script?
0570  *
0571  * @todo Test opaque RGB color space object with a non-export-all version
0572  * of this library to make sure it actually works for third-party developers.
0573  *
0574  * @todo Sometimes, on dual-screen setup, one screen has another DPI than
0575  * the other screen. Does this library behave correctly in these situations?
0576  *
0577  * @todo Would it make sense for @ref PerceptualColor::ChromaHueDiagram and
0578  * @ref PerceptualColor::ChromaLightnessDiagram to split up their property
0579  * <tt>currentColor</tt> into two properties: A two-dimensional property
0580  * for what the user can change, and a one-dimensional property
0581  * for what only the programmer can change? Or at least provide
0582  * a Q_INVOKABLE getter and maybe also setter support? So
0583  * @ref PerceptualColor::WheelColorPicker could use this
0584  * instead of a lambda expression to set the hue of the
0585  * @ref PerceptualColor::ChromaLightnessDiagram. And: Also when we don’t do
0586  * that: When setting <tt>currentColor</tt> to an out-of-gamut color,
0587  * what happens? Does @ref PerceptualColor::ChromaHueDiagram preserve
0588  * lightness, while @ref PerceptualColor::ChromaLightnessDiagram preserves
0589  * hue? Would this make sense?
0590  *
0591  * @todo Paint grayed-out handles for all widgets when setEnabled(false)
0592  * is used! For example 25% lightness instead of black. And 75% lightness
0593  * instead of white. But: Provide this information
0594  * in @ref PerceptualColor::AbstractDiagram!
0595  *
0596  * @todo It might be interesting to use <tt>QStyle::PM_FocusFrameHMargin</tt>
0597  * <em>(Horizontal margin that the focus frame will outset the widget
0598  * by.)</em> Or: <tt>QStyle::PM_FocusFrameVMargin</tt>. Using this for the
0599  * distance between the focus indicator and the actual content of the widget
0600  * maybe give a more <tt>QStyle</tt> compliant look. But: If using this,
0601  * ensurePolished() must be called before!
0602  *
0603  * @todo Use <tt>explicit</tt> on all constructors?
0604  *
0605  * @todo Screen picker with magnifier glass in two steps
0606  * similar to https://colorsnapper.com ? Or like in Firefox
0607  * (Menu → Weitere Werkzeuge → Farbpalette)?
0608  *
0609  * @todo Multi-licensing? Add Boost licence and Unlicense as an additional
0610  * choice?
0611  *
0612  * @todo The image cache for the gamut widgets should be updated
0613  * asynchronously (in its own thread or even various own threads
0614  * in parallel). While waiting for the result, an empty image could be used.
0615  * Or it might be useful to provide first a low-resolution version, and only
0616  * later-on a high-resolution version. Anyway, KDE provides an interesting
0617  * recommendation: <tt>int Units::humanMoment = 2000;</tt> <em>Time in
0618  * milliseconds equivalent to the theoretical human moment, which can be
0619  * used to determine whether how long to wait until the user should be
0620  * informed of something, or can be used as the limit for how long something
0621  * should wait before being automatically initiated. / Some examples: /
0622  * When the user types text in a search field, wait no longer than this
0623  * duration after the user completes typing before starting the search /
0624  * When loading data which would commonly arrive rapidly enough to not
0625  * require interaction, wait this long before showing a spinner</em> See
0626  * https://api.kde.org/frameworks/plasma-framework/html/classUnits.html#ab22ad7033b2e3d00a862650e82f5ba5e
0627  * for details.
0628  *
0629  * @todo HLC @ref PerceptualColor::MultiSpinBox Allow entering (on the
0630  * keyboard) of too big hues (361°), negative hues (-1°), negative chroma (-20)
0631  * and too big chroma (201 or 256) – but do not allow this with the arrows
0632  * (and how do the arrows react when currently one of these values is
0633  * shown?). Does this make sense? Anyway do <em>not</em> allow this for
0634  * lightness, because the lightness is <em>by definition</em> bound
0635  * to <tt>[0, 100]</tt>.
0636  *
0637  * @todo Multi-threaded application of color transforms. It seems okay to
0638  * create the color transforms in one thread and use the same color
0639  * transform (once created) from various other threads at the same time
0640  * as long as the flag <tt>cmsFLAGS_NOCACHE</tt> is used to create the
0641  * transform.
0642  *
0643  * @todo Automatically scale the thickness of the wheel (and maybe even the
0644  * handle) with varying widget size?
0645  *
0646  * @todo Support more color spaces? https://pypi.org/project/colorio/ for
0647  * example supports a lot of (also perceptually uniform) color spaces…
0648  *
0649  * @todo Export less symbols?
0650  *
0651  * @todo Check in all classes that take a @ref PerceptualColor::RgbColorSpace
0652  * that the shared pointer is actually not a <tt>nullptr</tt>. If is
0653  * <em>is</em> a <tt>nullptr</tt> than throw an exception. Throwing the
0654  * exception early might make error detection easier for users of the library.
0655  *
0656  * * @todo Avoid default arguments like <tt>void test(int i = 0)</tt> in
0657  * public headers, as changes require re-compilation of the client application
0658  * to take effect, which might lead to a miss-match of behaviour between
0659  * application and library, if  compile-time and run-time version of the
0660  * library are not the same. Is the problem  for default constructors
0661  * like <tt>ClassName() = default</tt> similar?
0662  *
0663  * @todo mark all public non-slot functions with Q_INVOKABLE (except property
0664  * setters and getters)
0665  *
0666  * @todo A good widget library should also be touchscreen-ready. Find
0667  * an alternative to @ref PerceptualColor::MultiSpinBox? How, for up
0668  * to 360 values (degrees in step by 1)? Or should the steps simply be bigger?
0669  *
0670  * @todo KDE Frameworks / https://marketplace.qt.io/ ?
0671  * https://community.kde.org/Incubator
0672  *
0673  * @todo Provide property bindings as described in
0674  * https://www.qt.io/blog/property-bindings-in-qt-6 or not? It is worth
0675  * when we do not support QML? What are the pitfalls? Imagine a property
0676  * that holds a percent value from 0 to 100; the setter enforces this
0677  * range; the binding bypasses the setter and allows every value? And:
0678  * How can callbacks know about when a setter was called in C++? See
0679  * also: https://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html
0680  * and https://doc.qt.io/qt-5/qtqml-tutorials-extending-qml-example.html and
0681  * http://blog.aeguana.com/2015/12/12/writing-a-gui-using-qml-for-a-c-project/
0682  * for interaction between QML and C++. Pitfalls: Example of color() property
0683  * stored internally at m_color: Much implementation code of the class will
0684  * access directly m_color instead of color(), so when using bindings,
0685  * this code is broken?
0686  *
0687  * @todo Provide QML support so that for
0688  * https://doc.qt.io/qt-5/qml-qtquick-dialogs-colordialog.html (or its
0689  * Qt6 counterpart) we provide a source compatible alternative, like for
0690  * QColorWidget? Split the library in three parts (Common, Widgets, QML)?
0691  * Support <a href="https://mauikit.org/">MauiKit</a>?
0692  *
0693  * @todo Apparently QWidget cannot be used from QML. (Though there is
0694  * https://www.kdab.com/declarative-widgets/ – how does that work?) Is it
0695  * therefore worth to have complete support for signals in all our QWidget
0696  * code if this is not really necessary for QWidget (for example for
0697  * properties that can only be changed by the library user and not by the
0698  * end user)?
0699  *
0700  * @todo Comply with <a href="https://community.kde.org/Policies">KDE
0701  * policies</a>.
0702  *
0703  * @todo Remove all qDebug calls from the source
0704  *
0705  * @todo Qt Designer support for the widgets. Quote from a blog from Viking
0706  * about Qt Designer plugins:
0707  * The problem is that you have to build it with exactly the same compiler
0708  * tool chain as designer was built with, and you have to do it in release
0709  * mode. Unless your Qt is built in debug, then your plugin needs to be
0710  * built in debug mode as well. So you can’t just always use the same
0711  * compiler as you build the application with, if you use the system Qt or
0712  * a downloaded Qt version.
0713  *
0714  * @todo Use <a href="https://lvc.github.io/abi-compliance-checker/">
0715  * abi-compliance-checker</a> to control ABI compatibility.
0716  *
0717  * @todo Follow KDE’s <a href="https://hig.kde.org/index.html">HIG</a>
0718  *
0719  * @todo Test linking against lcms.h in version 2.0.0 for compatibility
0720  * (or require more recent version?)
0721  *
0722  * @todo Require (by static cast additional to CMake conditions) a minimum
0723  * Qt version?
0724  *
0725  * @todo Would it be a good idea to implement Q_PROPERTY RESET overall? See
0726  * also https://phabricator.kde.org/T12359
0727  *
0728  * @todo Better design on small widget sizes for the whole library.
0729  *
0730  * @todo Anti-aliasing the gamut diagrams? Wouldn't this be bad for
0731  * performance?
0732  *
0733  * @todo Use a cross-hair cursor on @ref PerceptualColor::ChromaHueDiagram
0734  * and @ref PerceptualColor::ChromaLightnessDiagram when the mouse is
0735  * hovering over the gamut, to show that this surface can be clicked?
0736  *
0737  * @todo Touch-friendly interface: Would it be good to have buttons for
0738  * plus and minus on the various LCH axis which would be companions
0739  * for @ref PerceptualColor::ChromaHueDiagram and
0740  * @ref PerceptualColor::ChromaLightnessDiagram and would allow
0741  * more exactly choose colors also on touch devices?
0742  *
0743  * @todo Would it be a good idea to have plus and minus buttons that
0744  * manipulate the current color along the depth and vividness axis
0745  * as proposed in “Extending CIELAB - Vividness, V, depth, D, and clarity, T”
0746  * by Roy S. Berns?
0747  *
0748  * @todo Spell checking for the documentation, if possible also grammar
0749  * checking with LanguageTool */
0750 
0751 /** @page hidpisupport High DPI support
0752  *
0753  * This library supports High DPI out of the box.
0754  *
0755  * The only thing that requires special attention are icons.
0756  *
0757  * @section iconsupport Icon support
0758  *
0759  * This library uses by default a possibly existing icon theme
0760  * if available in Qt. Windows and Mac do not provide icon themes by
0761  * default, while Linux usually provides them. SVG is pretty much the standard
0762  * nowadays and the only reliably way to have crisp icons also on desktop
0763  * scales like 1.25 or 1.5. If high-DPI icons are available depends finally
0764  * on your operation system. Only if no icon at all is provided by the
0765  * operation system, the library falls back to built-in high-DPI SVG icons.
0766  *
0767  * Note that QSvgIconEnginePlugin is a mandatory run-time
0768  * dependency (see @ref build for details).
0769  *
0770  * @section qt5icons Qt5 legacy
0771  *
0772  * While <a href="https://bugreports.qt.io/browse/QTBUG-89279">Qt6
0773  * renders icons always with high-DPI</a> (if available),
0774  * Qt5 renders icons by default in low resolution. This applies even
0775  * for SVG icons on high-DPI displays! Application developers have to enable
0776  * high-DPI icon rendering manually with the following code (which should be
0777  * put by convention <em>before</em> creating the <tt>QCoreApplication</tt>
0778  * object):
0779  * <br/><tt>QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);</tt> */
0780 
0781 /** @page howtogetstarted How to get started
0782  *
0783  * How to get started? @ref PerceptualColor::ColorDialog provides a
0784  * perceptual replacement for QColorDialog:
0785  * @snippet testcolordialog.cpp ColorDialog Get color
0786  *
0787  * This is a minimal, but complete example project showing how to use
0788  * this library:
0789  *
0790  * CMakeLists.txt:
0791  * @include examples/CMakeLists.txt
0792  *
0793  * example.cpp:
0794  * @include examples/example.cpp */
0795 
0796 /** @page i18nl10n Internationalization and localization
0797  *
0798  * @section Internationalization
0799  *
0800  * This library is internationalized (i18n). This include also support
0801  * for right-to-left layouts in the widgets.
0802  *
0803  * @section Localization
0804  *
0805  * This library is also localized (l10n). The localization is divided
0806  * into two separate areas, which behave differently and independently
0807  * of each other.
0808  *
0809  * 1. Translation.
0810  * 2. Everything else.
0811  *
0812  * @subsection localizationtranslation Translation
0813  *
0814  * The translation of user-visible strings is a global setting for the whole
0815  * library. The language for the translation is auto-detected depending on
0816  * the settings of the current computer. You can specify the translation
0817  * explicitly with @ref PerceptualColor::setTranslation(), which can also
0818  * be used to change the translation dynamically (during program execution).
0819  * The various translations are build directly into the library binary;
0820  * no external files need to be available or loaded.
0821  *
0822  * @subsection localizationeverythingelse Everything else
0823  *
0824  * All other localization settings (like which decimal separator to use or
0825  * which date format to use) are individual per widget, depending on the
0826  * <tt><a href="https://doc.qt.io/qt-6/qwidget.html#locale-prop">
0827  * QWidget::locale()</a></tt> property. Changing the localization dynamically
0828  * (during program execution) is currently not supported.
0829  *
0830  * @internal
0831  *
0832  * @todo Support changing the localization dynamically (during program
0833  * execution). This affects also @ref PerceptualColor::MultiSpinBox and
0834  * the <tt>QSpinBox</tt> in @ref PerceptualColor::ColorDialog that is
0835  * used for the opacity and maybe also the RGB-Hex-LineEdit.
0836  *
0837  * @todo Provide more localizations! */
0838 
0839 /** @page licenseinfo License
0840  *
0841  * @copyright
0842  * - We follow the <a href="https://reuse.software/">“Reuse”
0843  *   specification</a>.
0844  * - The files from which the library (and this documentation as well)
0845  *   are generated do not all have the same license; instead, each file
0846  *   is subject to one of the following permissive licenses:
0847  *   - BSD-2-Clause OR MIT (for example, some C++ source code files)
0848  *   - MIT (for example, some icons)
0849  *   - BSD-3-Clause (for example, some CMake files)
0850  *   - CC0-1.0 (for example, some color profiles)
0851  * - Other parts of the codebase (which will
0852  *   <em>not</em> be installed by CMake, examples include <em>autotests</em>
0853  *   and <em>utils</em>) might have different licenses and/or include
0854  *   compiled-in resources that have different licenses. */
0855 
0856 /** @internal
0857  *
0858  * @page measurementdetails Measurement details
0859  *
0860  * When this library deals with raster graphics, it simultaneously uses
0861  * concepts concerning measurement. This page describes the terminology
0862  * used within the documentation of this library.
0863  *
0864  * @section introduction Introduction
0865  * Today’s displays have a wide range of physical pixel density (pixels
0866  * per length). Displays with a high physical pixel density are called
0867  * <b>High-DPI displays</b> or <b>HiDPI displays</b> or <b>Retina displays</b>.
0868  *
0869  * @section unitsofmeasurement Units of measurement
0870  * As Qt documentation says:
0871  *      “<em>Qt uses a model where the application coordinate system is
0872  *      independent of the display device resolution. The application
0873  *      operates in </em>device-independent pixels<em>, which are then
0874  *      mapped to the physical pixels of the display via a scale
0875  *      factor, known as the </em>device pixel ratio<em>.</em>”
0876  *
0877  * So when rendering widgets, there are two different units of measurement
0878  * to consider:
0879  * - <b>Device-independent pixels</b> are the  unit of measurement for
0880  *   widgets, windows, screens, mouse events and so on in Qt.
0881  * - <b>Physical pixels</b> are the unit that measures actual physical
0882  *   display pixels.
0883  *
0884  * The conversion factor between these two units of measurement is
0885  * <tt>QPaintDevice::devicePixelRatioF()</tt>, a floating point number.
0886  * It is usually <tt>1.00</tt> on classic low-resolution screens. It could be
0887  * for example <tt>1.25</tt> or <tt>2.00</tt> on displays with a higher
0888  * pixel density.
0889  *
0890  * @section coordinatepointsversuspixelpositions Coordinate points versus pixel positions
0891  *
0892  * - <b>Coordinate points</b> are points in the mathematical sense, that
0893  *   means they have zero surface. Coordinate points should be stored as
0894  *   <em>floating point numbers</em>.
0895  * - <b>Pixel positions</b> describe the position of a particular pixel
0896  *   within the pixel grid. Pixels are surfaces, not points. A pixel is a
0897  *   square of the width and length <tt>1</tt>. The pixel at position
0898  *   <tt>QPoint(x, y)</tt> is the square with the top-left edge at coordinate
0899  *   point <tt>QPoint(x, y)</tt> and the bottom-right edge at coordinate
0900  *   point <tt>QPoint(x+1, y+1)</tt>. Pixel positions should be stored
0901  *   as <em>integer numbers</em>.
0902  *
0903  * Some functions (like mouse events) work with pixel positions, other
0904  * functions (like antialiased floating-point drawing operations) work
0905  * with coordinate points. It’s important to always distinguish correctly
0906  * these two different concepts. See https://doc.qt.io/qt-6/coordsys.html
0907  * for more details about integer precision vs floating point precision
0908  * on drawing operations. */
0909 
0910 /** @page namespacepollution Name⁠space pollution
0911  *
0912  * This library avoids namespace pollution and collisions:
0913  *
0914  * - Macros are prefixed with <tt>PERCEPTUALCOLOR_</tt>.
0915  * - Symbols that have external linkage are within the
0916  *   namespace <tt>PerceptualColor</tt>. (Exception: The
0917  *   <a href="https://doc.qt.io/qt-5/resources.html">
0918  *   Qt resource system</a> generates functions prefixed
0919  *   with <tt>qInitResources_</tt> and <tt>qCleanupResources_</tt>
0920  *   that are not within the previously mentioned namespace.)
0921  * - Resources within the <a href="https://doc.qt.io/qt-5/resources.html">Qt
0922  *   resource system</a> are within the folder <tt>:/PerceptualColor/</tt>.  */
0923 
0924 /** @internal
0925  *
0926  * @page pimpl Pointer to implementation idiom
0927  *
0928  * This library uses the <em>pointer to implementation</em> idiom
0929  * (also known as pimpl idiom, d-pointer idiom or opaque-pointer idiom)
0930  * in almost all classes that are part of the public API, and also in
0931  * some classes that are part of the private API. The idiom is described
0932  * in detail in the Internet. The following flavour of the idiom is used
0933  * in our library:
0934  *
0935  * - The pointer to the implementation is called <tt>d_pointer</tt>. It’s of
0936  *   type @ref PerceptualColor::ConstPropagatingUniquePointer which provides
0937  *   const-correctness.
0938  * - The back pointer is called <tt>q_pointer</tt>. (A “q” is just a “d”
0939  *   pointing in a different direction, get it?). It’s
0940  *   of type @ref PerceptualColor::ConstPropagatingRawPointer which provides
0941  *   const-correctness.
0942  * - <a href="https://euroquis.nl//kde/2022/01/31/dptr.html"> The
0943  *   <tt>q_pointer</tt> <em>must not</em> ever be used in the destructor
0944  *   of the private implementation.</a> Rationale: All functions of the
0945  *   public class could potentially use the d_pointer. However, at the moment
0946  *   the destructor of the private class has started, the use of the d_pointer
0947  *   is already undefined behaviour. With some compilers this leads to an
0948  *   immediate crash, with other compilers it leads to
0949  *   silent undefined behaviour.
0950  *
0951  * The private classes are <em>not</em> nested
0952  * classes of their public counterpart. This is also
0953  * <a href="https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B#Using_a_d-Pointer">
0954  * what the the KDE community recommends</a>:
0955  * > It is also possible (but not recommended) to declare the private
0956  * > class […] as a nested private class (e.g. Foo::Private). […] remember
0957  * > that the nested private class will inherit the public symbol visibility
0958  * > of the containing exported class. This will cause the functions
0959  * > of the private class to be named in the dynamic library's symbol
0960  * > table. […] Other downsides […] include […] the fact that it can't be
0961  * > forward-declared in unrelated headers anymore (which can be useful to
0962  * > declare it as a friend class).
0963  *
0964  * @note This idiom is also used by Qt itself, and Qt even provides some macros
0965  * and extension points (<tt>Q_DECLARE_PRIVATE</tt>, <tt>Q_D</tt>, a protected
0966  * member called <tt>d_ptr</tt> in almost all classes…), that help dealing
0967  * with the pimpl idiom. Though available, these Qt features are not
0968  * officially documented; and they would also interfere with private
0969  * implementations of Qt itself without documented behaviour, which seems
0970  * inappropriate. Furthermore, the Qt pimpl idiom is complicate because
0971  * it uses (for performance reasons) inheritance between the private
0972  * implementation classes. This breaks, however, the encapsulation, because
0973  * all formerly private elements of a class become protected now. Our class
0974  * hierarchy is not that deep, so the performance gain might not be worth
0975  * the additional code complexity. Therefore, this library uses a more simple
0976  * pimpl idiom without inheritance of the private implementation. It has
0977  * however all the other features of the Qt pimpl idiom, including
0978  * <tt>const</tt> propagating access to the private implementation
0979  * thanks to @ref PerceptualColor::ConstPropagatingUniquePointer and
0980  * @ref PerceptualColor::ConstPropagatingRawPointer. And, at difference
0981  * to Qt’s pimpl idiom, it keeps private code strictly private.
0982  * Note however, that switching later from our current pimpl idiom to
0983  * the polymorphic Qt pimpl idiom would break the binary
0984  * compatibility. See also the document <em>
0985  * <a href="https://accu.org/journals/overload/18/100/love_1718/">Interface
0986  * Versioning in C++</a></em> and KDE’s information document <em>
0987  * <a
0988  * href="https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B">
0989  * Binary Compatibility Issues With C++</a></em> and for details.
0990  *
0991  * @note It would be nice to have the d_pointer and q_pointer
0992  * be themselves be declared <tt>const</tt>, because this would
0993  * clearly communicate that those pointers are not expected to change
0994  * the address they point to. Unfortunately, apparently this does not
0995  * work with neither @ref PerceptualColor::ConstPropagatingUniquePointer nor
0996  * @ref PerceptualColor::ConstPropagatingRawPointer as it would change also
0997  * all the access rights to the pointed object to always <tt>const</tt>. */
0998 
0999 /** @page qtstylesheetssupport Qt Style Sheets support
1000  *
1001  * The widget of this library supports the Qt Style Sheet
1002  * <a href="https://doc.qt.io/qt-6/stylesheet-reference.html#list-of-stylable-widgets">
1003  * properties of the Qt class they are derived from</a> only where it
1004  * makes sense. So you set the <tt>background-color</tt> of
1005  * a @ref PerceptualColor::MultiSpinBox. But you should not set
1006  * it for a @ref PerceptualColor::GradientSlider because the point
1007  * of this widget is to always use the gradient as the background;
1008  * the same applies for most widgets that showcase colors.
1009  *
1010  * When using class names of this library as
1011  * selectors in Qt Style Sheets, you have to
1012  * <a href="https://doc.qt.io/Qt-6/stylesheet-syntax.html#widgets-inside-c-namespaces">
1013  * substitute the namespace separator <tt>::</tt> by <tt>\--</tt></a>
1014  * to get a working selector: To select the class
1015  * @ref PerceptualColor::ColorDialog, use the selector
1016  * <tt>PerceptualColor\--ColorDialog</tt>. */
1017 
1018 /** @page lchrange Range of LCH values
1019  *
1020  *
1021  * The LCH values in this library are implemented with the following range:
1022  *
1023  * |               |    l     |    a     |    b     |    c     |    h     |
1024  * | :------------ | :------: | :------: | :------: |:-------: | :------: |
1025  * | CIELab/CIELCh | [0, 100] | [0, 255] | [0, 255] | [0, 255] | [0, 360[ |
1026  * | Oklab/Oklch   |  [0, 1]  |  [0, 2]  |  [0, 2]  |  [0, 2]  | [0, 360[ |
1027  *
1028  * This range is enough to cover the hole range of human perception. (Note
1029  * that the actual range of human perception has an irregular shape and
1030  * covers only parts of all possible combinations of LCH values. And
1031  * the actual gamut of real-word output devices is smaller than the
1032  * human perception.)
1033  *
1034  * @internal
1035  *
1036  * @section lchrangerationale Rationale
1037  *
1038  * The gamut of actual human perception within the LAB color model (and
1039  * its alternative representation LCH) has an irregular shape. Its maximum
1040  * extensions:
1041  *
1042  * <b>Lightness (L)</b>
1043  * The maximum range for LAB/LCH lightness is limited by
1044  * definition: <tt>[0, 100]</tt> for CIELch and <tt>[0, 1]</tt> for Oklch.
1045  *
1046  * <b>Hue (H)</b>
1047  * The maximum range for LCH hue is limited by definition to
1048  * the full circle: <tt>[0°, 360°[</tt>.
1049  *
1050  * <b>a, b, Chroma (C)</b>
1051  * The maximum range for a, b and Chroma (C) is complex. It is <em>not</em>
1052  * limited by definition. A useful limit is the actual human perception.
1053  *
1054  * | CIELab/CIELCh                 |        a          |         b         |      C      |
1055  * | :---------------------------- |:----------------: | :---------------: | :---------: |
1056  * | Usual implementation¹         |    [−128, 127]    |    [−128, 127]    |             |
1057  * | Human perception (Wikipedia)² |    [−170, 100]    |    [−100, 150]    |             |
1058  * | Human perception (2° D50)³    | [−165.39, 129.05] | [−132.62, 146.69] | [0, 183.42] |
1059  * | Human perception (2° D65)³    | [−170.84, 147.84] | [−129.66, 146.78] | [0, 194.84] |
1060  * | Human perception (10° D65)³   | [−164.29, 115.14] | [−116.10, 145.53] | [0, 186.17] |
1061  *
1062  * 1. The range of  <tt>[−128, 127]</tt> is in C++ a signed 8‑bit integer. But
1063  *    this data type usually used in software implementations is (as the table
1064  *    clearly shows) not enough to cover the hole range of actual human
1065  *    color perception.
1066  * 2. Ranges of CIELAB coordinates according to the
1067  *    <a href="https://de.wikipedia.org/w/index.php?title=Lab-Farbraum&oldid=197156292">
1068  *    German Wikipedia</a>.
1069  * 3. The German association <em>Freie Farbe e. V.</em> has
1070  *    published a calculation of the
1071  *    <a href="https://www.freiefarbe.de/artikel/grenzen-des-cielab-farbraums/">
1072  *    shape of actual human perception</a> for various observation angles
1073  *    and illuminants. This data contains only the CIELAB coordinates
1074  *    (L, a, b). From this data, the chroma (C) component can be calculated
1075  *    easily as Pythagoras of the a axis and b axis value pairs:
1076  *    √(a² + b²) = C.
1077  *
1078  * Logically, the chroma value can reach higher values than a and b, however,
1079  * for simplicity it seems appropriate to use the same range for chroma, a and
1080  * b. Following these tables, the maximum chroma in human perception in CIELCh
1081  * is <tt>194.84</tt>. As apparently this depends on viewing  conditions,
1082  * it might be a good idea to use a slightly higher limit, to be sure that the
1083  * value will never be too small. Here, <tt>200</tt> might be a good candidate.
1084  * However, some gamuts are wider. The <em>LargeRGB-elle-V2-g22.icc</em>
1085  * profile goes up to a chroma value of 245. Finally, we have fixed the valid
1086  * range to 255, because this is for sure enough to cover the human
1087  * perception, and it will cover almost all existing profiles.
1088  *
1089  * For Oklch we have observed up to 1.52 as chroma values when using the
1090  * <em>LargeRGB-elle-V2-g22.icc</em> profile. As with CIELCh chroma, we have
1091  * added a safety margin, rounded up to the next integer, and finally
1092  * chosen 2 as maximum.
1093  *
1094  * @internal
1095  *
1096  * @sa @ref PerceptualColor::CielchD50Values::maximumChroma
1097  * @sa @ref PerceptualColor::OklchValues::maximumChroma
1098  *
1099  * @todo Why is the exact extend of non-imaginary colors unknown? Could it be
1100  * deduced from the <a href="https://en.m.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space">
1101  * CIE xy chromacity diagram</a>? And: Is 255 enough even for large color
1102  * spaces like <a href="https://en.m.wikipedia.org/wiki/Rec._2020">
1103  * Rec. 2020</a> or <a href="https://en.m.wikipedia.org/wiki/DCI-P3">
1104  * DCI-P3</a>?
1105  */
1106 
1107 /** @page versioninfo Version information at compiletime and runtime
1108  *
1109  * This library uses
1110  * <a href="https://semver.org/">Semantic Versioning 2.0.0</a>.
1111  *
1112  * Version information is provided by the header <tt>version.h</tt>
1113  *
1114  * To know against which version of this library you are <em>running</em>, use
1115  * - @ref PerceptualColor::perceptualColorRunTimeVersion
1116  *
1117  * To know against which version of this library you are <em>compiling</em>,
1118  * use
1119  * - @ref PERCEPTUALCOLOR_COMPILE_TIME_VERSION
1120  * - @ref PERCEPTUALCOLOR_COMPILE_TIME_VERSION_MAJOR
1121  * - @ref PERCEPTUALCOLOR_COMPILE_TIME_VERSION_MINOR
1122  * - @ref PERCEPTUALCOLOR_COMPILE_TIME_VERSION_PATCH */
1123 
1124 /** @brief The namespace of this library.
1125  *
1126  * All symbols that are provided in this library are encapsulated within this
1127  * namespace. */
1128 namespace PerceptualColor
1129 {
1130 } // namespace PerceptualColor