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 #ifndef CSSCOLOR_H
0005 #define CSSCOLOR_H
0006 
0007 #include "genericcolor.h"
0008 #include "helperconversion.h"
0009 #include <optional>
0010 #include <qglobal.h>
0011 #include <qhash.h>
0012 #include <qrgb.h>
0013 #include <qstring.h>
0014 
0015 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0016 #include <qcontainerfwd.h>
0017 #include <qtmetamacros.h>
0018 #else
0019 #include <qstringlist.h>
0020 #endif
0021 
0022 namespace PerceptualColor
0023 {
0024 
0025 /** @internal
0026  *
0027  * @brief Toolbox for CSS colors. */
0028 class CssColor
0029 {
0030 public:
0031     /** @brief Represents the
0032      * <a href="https://www.w3.org/TR/css-color-4/#typedef-predefined-rgb">
0033      * predefined RGB color spaces</a> of CSS Color 4. */
0034     enum class CssPredefinedRgbColorSpace {
0035         Invalid, /**< Represents a non-existing color space. */
0036         Srgb, /**<
0037             <a href="https://www.w3.org/TR/css-color-4/#valdef-color-srgb">
0038             srgb</a> */
0039         SrgbLinear, /**<
0040             <a href="https://www.w3.org/TR/css-color-4/#valdef-color-srgb-linear">
0041             srgb-linear</a> */
0042         DisplayP3, /**<
0043             <a href="https://www.w3.org/TR/css-color-4/#valdef-color-display-p3">
0044             display-p3</a> */
0045         A98Rgb, /**<
0046            <a href="https://www.w3.org/TR/css-color-4/#valdef-color-a98-rgb">
0047            a98-rgb</a> */
0048         ProphotoRgb, /**<
0049            <a href="https://www.w3.org/TR/css-color-4/#valdef-color-prophoto-rgb">
0050            prophoto-rgb</a> */
0051         Rec2020 /**<
0052             <a href="https://www.w3.org/TR/css-color-4/#valdef-color-rec2020">
0053             rec2020</a> */
0054     };
0055     Q_ENUM(CssPredefinedRgbColorSpace)
0056 
0057     /** @internal
0058      *
0059      * @brief Represents a CSS color in a structured fashion. */
0060     struct CssColorValue {
0061     public:
0062         /** @brief The color model.
0063          *
0064          * This is @ref ColorModel::Invalid if the whole value is invalid. */
0065         ColorModel model = ColorModel::Invalid;
0066         /** @brief Which RGB profile is used.
0067          *
0068          * If @ref model is an RGB-based model, it contains
0069          * <em>which</em> RGB profile is used. Otherwise, it’s
0070          * @ref CssPredefinedRgbColorSpace::Invalid. */
0071         CssPredefinedRgbColorSpace rgbColorSpace = CssPredefinedRgbColorSpace::Invalid;
0072         /** @brief The numeric color description. */
0073         GenericColor color = GenericColor();
0074         /** @brief Opacity (alpha channel).
0075          *
0076          * Range: [0, 1] */
0077         double alpha1 = 0;
0078     };
0079 
0080     [[nodiscard]] static CssColorValue parse(const QString &string);
0081     [[nodiscard]] static QStringList generateCss(const QHash<ColorModel, GenericColor> &input, const double opacity1, const int significantFigures);
0082 
0083 private:
0084     /** @brief Syntaxes of the CSS Color 4 color functions. */
0085     enum class FunctionSyntax {
0086         LegacySyntax, /**< Only
0087             <a href="https://www.w3.org/TR/css-color-4/#color-syntax-legacy">
0088             Legacy (comma-separated) syntax</a>. */
0089         StandardSyntax, /**< Only
0090             <a href="https://www.w3.org/TR/css-color-4/#color-syntax">Standard
0091             (whitespace-separated) syntax</a>, optionally with a slash and an
0092             alpha argument at the end. */
0093         BothSyntaxes /**< Both, @ref FunctionSyntax::LegacySyntax and
0094             @ref FunctionSyntax::StandardSyntax. */
0095     };
0096 
0097     [[nodiscard]] static CssColorValue parseAbsoluteColorFunction(const QString &colorFunction);
0098     [[nodiscard]] static std::optional<QStringList> parseAllFunctionArguments(const QString &arguments, const FunctionSyntax mode, const int count);
0099     [[nodiscard]] static std::optional<QRgb> parseHexColor(const QString &hexColor);
0100     [[nodiscard]] static std::optional<QRgb> parseNamedColor(const QString &namedColor);
0101     [[nodiscard]] static std::optional<double> parseArgumentHueNoneTo360(const QString &argument);
0102     [[nodiscard]] static std::optional<double> parseArgumentPercentNoneTo1(const QString &argument);
0103     [[nodiscard]] static std::optional<double> parseArgumentPercentNumberNone(const QString &argument, const double full, const double none);
0104     [[nodiscard]] static std::optional<QStringList> validateArguments(const QStringList &arguments);
0105 
0106     /** @internal @brief Only for unit tests. */
0107     friend class TestCssColor;
0108 };
0109 
0110 } // namespace PerceptualColor
0111 
0112 #endif // CSSCOLOR_H