File indexing completed on 2024-06-16 04:16:10

0001 /*
0002     SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef H_KIS_COLOR_SELECTOR_H
0008 #define H_KIS_COLOR_SELECTOR_H
0009 
0010 #include <QWidget>
0011 #include <QVector>
0012 #include <QImage>
0013 #include <QPainterPath>
0014 
0015 #include "kis_color.h"
0016 #include "kis_radian.h"
0017 #include "kis_acs_types.h"
0018 #include "kis_signal_compressor_with_param.h"
0019 
0020 #include <resources/KoGamutMask.h>
0021 
0022 class QPainter;
0023 class KisDisplayColorConverter;
0024 class QTransform;
0025 
0026 class KisColorSelector: public QWidget
0027 {
0028     Q_OBJECT
0029 
0030     typedef KisRadian<qreal> Radian;
0031 
0032     struct ColorRing
0033     {
0034         ColorRing()
0035             : saturation(0)
0036             , outerRadius(0)
0037             , innerRadius(0)
0038         { }
0039 
0040         qreal                 saturation;
0041         qreal                 outerRadius;
0042         qreal                 innerRadius;
0043         QVector<QPainterPath> pieced;
0044     };
0045 
0046 public:
0047     KisColorSelector(QWidget* parent, KisColor::Type type=KisColor::HSL);
0048 
0049     void setColorSpace(KisColor::Type type);
0050     void setColorConverter(KisDisplayColorConverter* colorConverter);
0051     void setNumPieces(int num);
0052     void setNumLightPieces(int num);
0053     void setNumRings(int num);
0054 
0055     void setLight(qreal light=0.0f);
0056 
0057     void setLumaCoefficients(qreal lR, qreal lG, qreal lB, qreal lGamma);
0058     inline qreal lumaR() const { return m_lumaR; }
0059     inline qreal lumaG() const { return m_lumaG; }
0060     inline qreal lumaB() const { return m_lumaB; }
0061     inline qreal lumaGamma() const { return m_lumaGamma; }
0062 
0063     void setInverseSaturation(bool inverse);
0064     void selectColor(const KisColor& color);
0065     void setFgColor(const KoColor& fgColor);
0066     void setBgColor(const KoColor& bgColor);
0067 
0068     void setDefaultHueSteps(int num);
0069     void setDefaultSaturationSteps(int num);
0070     void setDefaultValueScaleSteps(int num);
0071     void setShowBgColor(bool value);
0072     void setShowValueScaleNumbers(bool value);
0073     void setGamutMask(KoGamutMaskSP gamutMask);
0074     void setDirty();
0075     bool gamutMaskOn();
0076     void setGamutMaskOn(bool gamutMaskOn);
0077     void setEnforceGamutMask(bool enforce);
0078     KoGamutMaskSP gamutMask();
0079 
0080     void saveSettings();
0081     void loadSettings();
0082 
0083     KisColor::Type getColorSpace       () const { return m_colorSpace;        }
0084     qint32         getNumRings         () const { return m_colorRings.size(); }
0085     qint32         getNumPieces        () const { return m_numPieces;         }
0086     qint32         getNumLightPieces   () const { return m_numLightPieces;    }
0087     bool           isSaturationInverted() const { return m_inverseSaturation; }
0088 
0089     quint32        getDefaultHueSteps  () const { return m_defaultHueSteps;        }
0090     quint32        getDefaultSaturationSteps () const { return m_defaultSaturationSteps;        }
0091     quint32        getDefaultValueScaleSteps () const { return m_defaultValueScaleSteps;        }
0092     bool           getShowBgColor () const { return m_showBgColor;        }
0093     bool           getShowValueScaleNumbers () const { return m_showValueScaleNumbers;        }
0094     bool           enforceGamutMask () const { return m_enforceGamutMask;        }
0095 
0096 Q_SIGNALS:
0097     void sigFgColorChanged(const KisColor& color);
0098     void sigBgColorChanged(const KisColor& color);
0099 
0100 private:
0101     void mousePressEvent(QMouseEvent* event) override;
0102     void mouseMoveEvent(QMouseEvent* event) override;
0103     void mouseReleaseEvent(QMouseEvent* event) override;
0104     void resizeEvent(QResizeEvent* event) override;
0105     void paintEvent(QPaintEvent* event) override;
0106     void leaveEvent(QEvent* e) override;
0107 
0108     bool colorIsClear(const KisColor &color);
0109     bool colorIsClear(const QPointF &colorPoint);
0110     void requestUpdateColorAndPreview(const KisColor &color, Acs::ColorRole role);
0111 
0112     void recalculateAreas(quint8 numLightPieces);
0113     void recalculateRings(quint8 numRings, quint8 numPieces);
0114     void createRing(ColorRing& wheel, quint8 numPieces, qreal innerRadius, qreal outerRadius);
0115 
0116     void drawRing(QPainter& painter, ColorRing& wheel, const QRect& rect);
0117     void drawOutline(QPainter& painter, const QRect& rect);
0118     void drawBlip(QPainter& painter, const QRect& rect);
0119     void drawLightStrip(QPainter& painter, const QRect& rect);
0120     void drawGamutMaskShape(QPainter& painter, const QRect& rect);
0121     void drawColorPreview(QPainter& painter, const QRect& rect);
0122 
0123     qint8 getHueIndex(Radian hue) const;
0124     qreal getHue(int hueIdx, Radian shift=0.0f) const;
0125     qint8 getLightIndex(const QPointF& pt) const;
0126     qint8 getLightIndex(qreal light) const;
0127     qreal getLight(const QPointF& pt) const;
0128     qint8 getSaturationIndex(const QPointF& pt) const;
0129     qint8 getSaturationIndex(qreal saturation) const;
0130     qreal getSaturation(int saturationIdx) const;
0131 
0132     QPointF mapCoordToView(const QPointF& pt, const QRectF& viewRect) const;
0133     QPointF mapCoordToUnit(const QPointF& pt, const QRectF& viewRect) const;
0134     QPointF mapColorToUnit(const KisColor& color, bool invertSaturation = true) const;
0135     Radian mapCoordToAngle(qreal x, qreal y) const;
0136     QPointF mapHueToAngle(qreal hue) const;
0137 
0138 public:
0139     // This is a private interface for signal compressor, don't use it.
0140     // Use requestUpdateColorAndPreview() instead
0141     void slotUpdateColorAndPreview(QPair<KisColor, Acs::ColorRole> color);
0142 
0143 private:
0144     KisDisplayColorConverter* m_colorConverter;
0145     KisColor::Type     m_colorSpace;
0146     quint8             m_numPieces;
0147     quint8             m_numLightPieces;
0148     bool               m_inverseSaturation;
0149     qint8              m_selectedRing;
0150     qint8              m_selectedPiece;
0151     qint8              m_selectedLightPiece;
0152     KisColor           m_selectedColor;
0153     KisColor           m_fgColor;
0154     KisColor           m_bgColor;
0155     QImage             m_renderBuffer;
0156     QImage             m_maskBuffer;
0157     QImage             m_lightStripBuffer;
0158     QImage             m_colorPreviewBuffer;
0159     QRect              m_widgetArea;
0160     QRect              m_renderArea;
0161     QRect              m_lightStripArea;
0162     bool               m_mouseMoved;
0163     QPointF            m_clickPos;
0164     qint8              m_clickedRing;
0165     QVector<ColorRing> m_colorRings;
0166     Qt::MouseButtons   m_pressedButtons;
0167 
0168     // docker settings
0169     quint8 m_defaultHueSteps;
0170     quint8 m_defaultSaturationSteps;
0171     quint8 m_defaultValueScaleSteps;
0172     bool m_showValueScaleNumbers {false};
0173     bool m_showBgColor {true};
0174 
0175     bool m_gamutMaskOn;
0176     KoGamutMaskSP m_currentGamutMask;
0177     bool m_enforceGamutMask;
0178 //    QSize m_renderAreaSize;
0179     bool m_maskPreviewActive;
0180 //    KisGamutMaskViewConverter* m_viewConverter;
0181     QTransform m_gamutMaskViewTransform;
0182 
0183     bool m_widgetUpdatesSelf;
0184     bool m_isDirtyWheel;
0185     bool m_isDirtyLightStrip;
0186     bool m_isDirtyGamutMask;
0187     bool m_isDirtyColorPreview;
0188 
0189     qreal m_lumaR;
0190     qreal m_lumaG;
0191     qreal m_lumaB;
0192     qreal m_lumaGamma;
0193 
0194     typedef KisSignalCompressorWithParam<QPair<KisColor, Acs::ColorRole>> ColorCompressorType;
0195     QScopedPointer<ColorCompressorType> m_updateColorCompressor;
0196 };
0197 
0198 #endif // H_KIS_COLOR_SELECTOR_H