File indexing completed on 2024-04-28 15:27:40

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include <QColor>
0010 #include <QJSValue>
0011 #include <QObject>
0012 #include <QQuickItem>
0013 
0014 /**
0015  * Utilities for processing items to obtain colors and information useful for
0016  * UIs that need to adjust to variable elements.
0017  */
0018 class ColorUtils : public QObject
0019 {
0020     Q_OBJECT
0021 public:
0022     /**
0023      * @brief Describes the contrast of an item.
0024      */
0025     enum Brightness {
0026         /**
0027          * @brief The item is dark and requires a light foreground color to achieve readable contrast.
0028          */
0029         Dark,
0030 
0031         /**
0032          * @brief The item is light and requires a dark foreground color to achieve readable contrast.
0033          */
0034         Light,
0035     };
0036     Q_ENUM(Brightness)
0037 
0038     explicit ColorUtils(QObject *parent = nullptr);
0039 
0040     /**
0041      * @brief This method returns whether a color is light or dark.
0042      *
0043      * Example usage:
0044      * @code{.qml}
0045      * import QtQuick 2.0
0046      * import org.kde.kirigami 2.12 as Kirigami
0047      *
0048      * Kirigami.Heading {
0049      *     text: {
0050      *         if (Kirigami.ColorUtils.brightnessForColor("pink") == Kirigami.ColorUtils.Light) {
0051      *             return "The color is light"
0052      *         } else {
0053      *             return "The color is dark"
0054      *         }
0055      *     }
0056      * }
0057      * @endcode
0058      *
0059      * @since KDE Frameworks 5.69
0060      * @since org.kde.kirigami 2.12
0061      */
0062     Q_INVOKABLE ColorUtils::Brightness brightnessForColor(const QColor &color);
0063 
0064     /**
0065      * @brief This method returns the color's estimated brightness.
0066      *
0067      * Similar to brightnessForColor but returns a 0 to 1 value for an
0068      * estimate of the equivalent gray light value (luma).
0069      * 0 as full black, 1 as full white and 0.5 equivalent to a 50% gray.
0070      *
0071      * @since KDE Frameworks 5.81
0072      * @since org.kde.kirigami 2.16
0073      */
0074     Q_INVOKABLE qreal grayForColor(const QColor &color);
0075 
0076     /**
0077      * @brief This method returns the result of overlaying the foreground color
0078      * on the background color.
0079      *
0080      * @param foreground The color to overlay on the background.
0081      * @param background The color to overlay the foreground on.
0082      *
0083      * Example usage:
0084      * @code{.qml}
0085      * import QtQuick 2.0
0086      * import org.kde.kirigami 2.12 as Kirigami
0087      *
0088      * Rectangle {
0089      *     color: Kirigami.ColorUtils.alphaBlend(Qt.rgba(0, 0, 0, 0.5), Qt.rgba(1, 1, 1, 1))
0090      * }
0091      * @endcode
0092      *
0093      * @since KDE Frameworks 5.69
0094      * @since org.kde.kirigami 2.12
0095      */
0096     Q_INVOKABLE QColor alphaBlend(const QColor &foreground, const QColor &background);
0097 
0098     /**
0099      * @brief This method returns a linearly interpolated color between color
0100      * one and color two.
0101      *
0102      * @param one The color to linearly interpolate from.
0103      * @param two The color to linearly interpolate to.
0104      * @param balance The balance between the two colors. 0.0 will return the
0105      * first color, 1.0 will return the second color. Values beyond these bounds
0106      * are valid, and will result in extrapolation.
0107      *
0108      * Example usage:
0109      * @code{.qml}
0110      * import QtQuick 2.0
0111      * import org.kde.kirigami 2.12 as Kirigami
0112      *
0113      * Rectangle {
0114      *     color: Kirigami.ColorUtils.linearInterpolation("black", "white", 0.5)
0115      * }
0116      * @endcode
0117      *
0118      * @since KDE Frameworks 5.69
0119      * @since org.kde.kirigami 2.12
0120      */
0121     Q_INVOKABLE QColor linearInterpolation(const QColor &one, const QColor &two, double balance);
0122 
0123     /**
0124      * @brief Increases or decreases either RGB or HSL properties of the color
0125      * by fixed amounts.
0126      *
0127      * @param color The color to adjust.
0128      * @param adjustments The adjustments to apply to the color.
0129      *
0130      * @note `value` and `lightness` are aliases for the same value.
0131      *
0132      * @code{.js}
0133      * {
0134      *     red: real, // Range: -255 to 255
0135      *     green: real, // Range: -255 to 255
0136      *     blue: real, // Range: -255 to 255
0137      *     hue: real, // Range: -360 to 360
0138      *     saturation: real, // Range: -255 to 255
0139      *     value: real, // Range: -255 to 255
0140      *     lightness: real, // Range: -255 to 255
0141      *     alpha: real // Range: -255 to 255
0142      * }
0143      * @endcode
0144      *
0145      * @since KDE Frameworks 5.69
0146      * @since org.kde.kirigami 2.12
0147      */
0148     Q_INVOKABLE QColor adjustColor(const QColor &color, const QJSValue &adjustments);
0149 
0150     /**
0151      * @brief Smoothly scales colors by changing either RGB or HSL properties of
0152      * the color.
0153      *
0154      * @param color The color to adjust.
0155      * @param adjustments The adjustments to apply to the color. Each value must
0156      * be between `-100.0` and `100.0`. This indicates how far the property
0157      * should be scaled from its original to the maximum if positive or to the
0158      * minimum if negative.
0159      *
0160      * @note `value` and `lightness` are aliases for the same value.
0161      *
0162      * @code{.js}
0163      * {
0164      *     red: real,
0165      *     green: real,
0166      *     blue: real,
0167      *     saturation: real,
0168      *     lightness: real,
0169      *     value: real,
0170      *     alpha: real
0171      * }
0172      * @endcode
0173      *
0174      * @since KDE Frameworks 5.69
0175      * @since org.kde.kirigami 2.12
0176      */
0177     Q_INVOKABLE QColor scaleColor(const QColor &color, const QJSValue &adjustments);
0178 
0179     /**
0180      * @brief Tint a color using a separate alpha value.
0181      *
0182      * This does the same as Qt.tint() except that rather than using the tint
0183      * color's alpha value, it uses a separate value that gets multiplied with
0184      * the tint color's alpha. This avoids needing to create a new color just to
0185      * adjust an alpha value.
0186      *
0187      * @param targetColor The color to tint.
0188      * @param tintColor The color to tint with.
0189      * @param alpha The amount of tinting to apply.
0190      *
0191      * @returns The tinted color.
0192      *
0193      * @see QtQml.Qt.tint
0194      */
0195     Q_INVOKABLE QColor tintWithAlpha(const QColor &targetColor, const QColor &tintColor, double alpha);
0196 
0197     /**
0198      * @brief Returns the CIELAB chroma of the given color.
0199      *
0200      * CIELAB chroma may give a better quantification of how vibrant a color is compared to HSV saturation.
0201      *
0202      * @see https://en.wikipedia.org/wiki/Colorfulness
0203      * @see https://en.wikipedia.org/wiki/CIELAB_color_space
0204      */
0205     Q_INVOKABLE static qreal chroma(const QColor &color);
0206 
0207     struct XYZColor {
0208         qreal x = 0;
0209         qreal y = 0;
0210         qreal z = 0;
0211     };
0212 
0213     struct LabColor {
0214         qreal l = 0;
0215         qreal a = 0;
0216         qreal b = 0;
0217     };
0218 
0219     // Not for QML, returns the comvertion from srgb of a QColor and XYZ colorspace
0220     static ColorUtils::XYZColor colorToXYZ(const QColor &color);
0221 
0222     // Not for QML, returns the comvertion from srgb of a QColor and Lab colorspace
0223     static ColorUtils::LabColor colorToLab(const QColor &color);
0224 
0225     static qreal luminance(const QColor &color);
0226 };