File indexing completed on 2024-05-12 04:44:33
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 #ifndef GRADIENTIMAGEPARAMETERS_H 0005 #define GRADIENTIMAGEPARAMETERS_H 0006 0007 #include "lchadouble.h" 0008 #include <qglobal.h> 0009 #include <qimage.h> 0010 #include <qmetatype.h> 0011 #include <qsharedpointer.h> 0012 #include <qvariant.h> 0013 0014 namespace PerceptualColor 0015 { 0016 class AsyncImageRenderCallback; 0017 class RgbColorSpace; 0018 0019 /** @internal 0020 * 0021 * @brief Parameters for image of a gradient. 0022 * 0023 * For usage with @ref AsyncImageProvider. 0024 * 0025 * As the hue is a circular property, there exists two ways to go one hue to 0026 * another (clockwise or counter-clockwise). This gradient takes always the 0027 * shortest way. 0028 * 0029 * The image has properties that can be accessed by the corresponding setters 0030 * and getters or directly. You should explicitly set all values 0031 * <em>before</em> calling the first time @ref render(). 0032 * 0033 * This class supports HiDPI via its @ref setDevicePixelRatioF function. 0034 * 0035 * @todo Instead of providing an image that has actually the size that 0036 * has been requested, we could provide just a tile. The user would have 0037 * to tile the surface. In many cases, we could get away with much smaller 0038 * images. Attention: Test if this approach works fine when the screen scale 0039 * factor is not an integer! */ 0040 struct GradientImageParameters final { 0041 public: 0042 explicit GradientImageParameters(); 0043 [[nodiscard]] bool operator==(const GradientImageParameters &other) const; 0044 [[nodiscard]] bool operator!=(const GradientImageParameters &other) const; 0045 0046 /** @brief Pointer to @ref RgbColorSpace object */ 0047 QSharedPointer<PerceptualColor::RgbColorSpace> rgbColorSpace = nullptr; 0048 0049 [[nodiscard]] LchaDouble colorFromValue(qreal value) const; 0050 static void render(const QVariant &variantParameters, AsyncImageRenderCallback &callbackObject); 0051 void setDevicePixelRatioF(const qreal newDevicePixelRatioF); 0052 void setFirstColor(const LchaDouble &newFirstColor); 0053 void setGradientLength(const int newGradientLength); 0054 void setGradientThickness(const int newGradientThickness); 0055 void setSecondColor(const LchaDouble &newFirstColor); 0056 0057 private: 0058 /** @internal @brief Only for unit tests. */ 0059 friend class TestGradientImageParameters; 0060 0061 // Methods 0062 [[nodiscard]] static LchaDouble completlyNormalizedAndBounded(const LchaDouble &color); 0063 void updateSecondColor(); 0064 0065 // Data members 0066 /** @brief Internal storage of the device pixel ratio as floating point. 0067 * 0068 * @sa @ref setDevicePixelRatioF() */ 0069 qreal m_devicePixelRatioF = 1; 0070 /** @brief Internal storage of the first color. 0071 * 0072 * The color is normalized and bound to the LCH color space. 0073 * @sa @ref completlyNormalizedAndBounded() */ 0074 LchaDouble m_firstColorCorrected; 0075 /** @brief Internal storage for the gradient length, measured in 0076 * physical pixels. 0077 * 0078 * @sa @ref setGradientLength() */ 0079 int m_gradientLength = 0; 0080 /** @brief Internal storage for the gradient thickness, measured in 0081 * physical pixels. 0082 * 0083 * @sa @ref setGradientThickness() */ 0084 int m_gradientThickness = 0; 0085 /** @brief Internal storage of the image (cache). 0086 * 0087 * - If <tt>m_image.isNull()</tt> than either no cache is available 0088 * or @ref m_gradientLength or @ref m_gradientThickness is <tt>0</tt>. 0089 * Before using it, a new image has to be rendered. (If 0090 * @ref m_gradientLength or @ref m_gradientThickness is 0091 * <tt>0</tt>, this will be extremly fast.) 0092 * - If <tt>m_image.isNull()</tt> is <tt>false</tt>, than the cache 0093 * is valid and can be used directly. */ 0094 QImage m_image; 0095 /** @brief Internal storage of the second color (corrected and altered 0096 * value). 0097 * 0098 * The color is normalized and bound to the LCH color space. In an 0099 * additional step, it has been altered (by increasing or decreasing the 0100 * hue component in steps of 360°) to minimize the distance in hue 0101 * from this color to @ref m_firstColorCorrected. This is necessary to 0102 * easily allow to calculate the intermediate colors of the gradient, so 0103 * that they take the shortest way through the color space. 0104 * @sa @ref setFirstColor() 0105 * @sa @ref setSecondColor() 0106 * @sa @ref completlyNormalizedAndBounded() 0107 * @sa @ref updateSecondColor() */ 0108 LchaDouble m_secondColorCorrectedAndAltered; 0109 }; 0110 0111 } // namespace PerceptualColor 0112 0113 Q_DECLARE_METATYPE(PerceptualColor::GradientImageParameters) 0114 0115 #endif // GRADIENTIMAGEPARAMETERS_H