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 COLORWHEELIMAGE_H
0005 #define COLORWHEELIMAGE_H
0006 
0007 #include <qglobal.h>
0008 #include <qimage.h>
0009 #include <qsharedpointer.h>
0010 
0011 namespace PerceptualColor
0012 {
0013 class RgbColorSpace;
0014 
0015 /** @internal
0016  *
0017  *  @brief An image of a color wheel.
0018  *
0019  * The image has properties that can be accessed by the corresponding setters
0020  * and getters.
0021  *
0022  * This class has a cache. The data is cached because it is expensive to
0023  * calculate it again and again on the fly.
0024  *
0025  * When changing one of the properties, the image is <em>not</em> calculated
0026  * immediately. But the old image in the cache is deleted, so that this
0027  * memory becomes immediately available. Once you use @ref getImage() the next
0028  * time, a new image is calculated and cached. As long as you do not change
0029  * the properties, the next call of @ref getImage() will be very fast, as
0030  * it returns just the cache.
0031  *
0032  * This class is intended for usage in widgets that need to display a
0033  * color wheel. It is recommended to update the properties of this class as
0034  * early as possible: If your widget is resized, use immediately also
0035  * @ref setImageSize to update this object. (This will reduce your memory
0036  * usage, as no memory will be hold for data that will not be
0037  * needed again.)
0038  *
0039  * This class supports HiDPI via its @ref setDevicePixelRatioF function.
0040  *
0041  * @note Resetting a property to its very same value does not trigger an
0042  * image calculation. So, if the border is 5, and you call @ref setBorder
0043  * <tt>(5)</tt>, than this will not trigger an image calculation, but the
0044  * cache stays valid and available.
0045  *
0046  * @note This class is not based on <tt>QCache</tt> or <tt>QPixmapCache</tt>
0047  * because the semantic is different.
0048  *
0049  * @note This class is not part of the public API, but just for internal
0050  * usage. Therefore, its interface is incomplete and contains only the
0051  * functions that are really used in the rest of the source code (property
0052  * setters are available, but getters might be missing), and it does not use
0053  * the pimpl idiom either.
0054  *
0055  * @internal
0056  *
0057  * @todo Port this class to @ref AsyncImageProvider, and do so with
0058  * interlacing support. */
0059 class ColorWheelImage final
0060 {
0061 public:
0062     explicit ColorWheelImage(const QSharedPointer<PerceptualColor::RgbColorSpace> &colorSpace);
0063     [[nodiscard]] QImage getImage();
0064     void setBorder(const qreal newBorder);
0065     void setDevicePixelRatioF(const qreal newDevicePixelRatioF);
0066     void setImageSize(const int newImageSize);
0067     void setWheelThickness(const qreal newWheelThickness);
0068 
0069 private:
0070     Q_DISABLE_COPY(ColorWheelImage)
0071 
0072     /** @internal @brief Only for unit tests. */
0073     friend class TestColorWheelImage;
0074 
0075     /** @brief Internal store for the border size, measured in physical pixels.
0076      *
0077      * @sa @ref setBorder() */
0078     qreal m_borderPhysical = 0;
0079     /** @brief Internal storage of the device pixel ratio as floating point.
0080      *
0081      * @sa @ref setDevicePixelRatioF() */
0082     qreal m_devicePixelRatioF = 1;
0083     /** @brief Internal storage of the image (cache).
0084      *
0085      * - If <tt>m_image.isNull()</tt> than either no cache is available
0086      *   or @ref m_imageSizePhysical is <tt>0</tt>. Before using it,
0087      *   a new image has to be rendered. (If @ref m_imageSizePhysical
0088      *   is <tt>0</tt>, this will be extremely fast.)
0089      * - If <tt>m_image.isNull()</tt> is <tt>false</tt>, than the cache
0090      *   is valid and can be used directly. */
0091     QImage m_image;
0092     /** @brief Internal store for the image size, measured in physical pixels.
0093      *
0094      * @sa @ref setImageSize() */
0095     int m_imageSizePhysical = 0;
0096     /** @brief Pointer to @ref RgbColorSpace object */
0097     QSharedPointer<PerceptualColor::RgbColorSpace> m_rgbColorSpace;
0098     /** @brief Internal store for the image size, measured in physical pixels.
0099      *
0100      * @sa @ref setWheelThickness() */
0101     qreal m_wheelThicknessPhysical = 0;
0102 };
0103 
0104 } // namespace PerceptualColor
0105 
0106 #endif // COLORWHEELIMAGE_H