File indexing completed on 2024-05-12 16:02:06
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #ifndef KIS_VISUAL_COLOR_SELECTOR_SHAPE_H 0007 #define KIS_VISUAL_COLOR_SELECTOR_SHAPE_H 0008 0009 #include <QWidget> 0010 #include <QScopedPointer> 0011 #include <QPixmap> 0012 #include <QRegion> 0013 #include <QMouseEvent> 0014 0015 #include <KoColor.h> 0016 #include <KoColorSpace.h> 0017 #include "KoColorDisplayRendererInterface.h" 0018 0019 #include "KisVisualColorSelector.h" 0020 #include "KisColorSelectorConfiguration.h" 0021 0022 /** 0023 * @brief The KisVisualColorSelectorShape class 0024 * A 2d widget can represent at maximum 2 coordinates. 0025 * So first decide howmany coordinates you need. (onedimensional, or twodimensional) 0026 * Then the model, (Channel, HSV, HSL, HSI, YUV). Channel is the raw color channels. 0027 * When it finds a non-implemented feature it'll return to Channel. 0028 * Then, select the channels you wish to be affected. This uses the model, so for cmyk 0029 * the channel is c=0, m=1, y=2, k=3, but for hsv, hue=0, sat=1, and val=2 0030 * These can also be set with 'slotsetactive channels'. 0031 * Then finally, connect the displayrenderer, you can also do this with 'setdisplayrenderer' 0032 * 0033 * Either way, this class is made to be subclassed, with a few virtuals so that the geometry 0034 * can be calculated properly. 0035 */ 0036 0037 class KisVisualColorSelectorShape : public QWidget 0038 { 0039 Q_OBJECT 0040 public: 0041 /** 0042 * @brief The Dimensions enum 0043 * Whether or not the shape is single or two dimensional. 0044 **/ 0045 enum Dimensions{onedimensional, twodimensional}; 0046 enum ColorModel{Channel, HSV, HSL, HSI, HSY, YUV}; 0047 explicit KisVisualColorSelectorShape(QWidget *parent, 0048 KisVisualColorSelectorShape::Dimensions dimension, 0049 const KoColorSpace *cs, 0050 int channel1, int channel2, 0051 const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); 0052 ~KisVisualColorSelectorShape() override; 0053 0054 /** 0055 * @brief getCursorPosition 0056 * @return current cursor position in shape-coordinates. 0057 */ 0058 QPointF getCursorPosition(); 0059 /** 0060 * @brief getDimensions 0061 * @return whether this is a single or twodimensional widget. 0062 */ 0063 Dimensions getDimensions() const; 0064 /** 0065 * @brief getPixmap 0066 * @return the pixmap of the gradient, for drawing on with a subclass. 0067 * the pixmap will not change unless 'm_d->setPixmap=true' which is toggled by 0068 * refresh and update functions. 0069 */ 0070 bool imagesNeedUpdate() const; 0071 QImage getImageMap(); 0072 const QImage getAlphaMask() const; 0073 /** 0074 * @brief setFullImage 0075 * Set the full widget image to be painted. 0076 * @param full this should be the full image. 0077 */ 0078 void setFullImage(QImage full); 0079 /** 0080 * @brief getCurrentColor 0081 * @return the current kocolor 0082 */ 0083 KoColor getCurrentColor(); 0084 /** 0085 * @brief setDisplayRenderer 0086 * disconnect the old display renderer if needed and connect the new one. 0087 * @param displayRenderer 0088 */ 0089 void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer); 0090 /** 0091 * @brief getColorFromConverter 0092 * @param c a koColor. 0093 * @return get the qcolor from the given kocolorusing this widget's display renderer. 0094 */ 0095 QColor getColorFromConverter(KoColor c); 0096 0097 /** 0098 * @brief getSpaceForSquare 0099 * @param geom the full widget rectangle 0100 * @return rectangle with enough space for second widget 0101 */ 0102 virtual QRect getSpaceForSquare(QRect geom) = 0; 0103 virtual QRect getSpaceForCircle(QRect geom) = 0; 0104 virtual QRect getSpaceForTriangle(QRect geom) = 0; 0105 0106 /** 0107 * @brief forceImageUpdate 0108 * force the image to recache. 0109 */ 0110 void forceImageUpdate(); 0111 0112 /** 0113 * @brief setBorderWidth 0114 * set the border of the single dimensional selector. 0115 * @param width 0116 */ 0117 virtual void setBorderWidth(int width) = 0; 0118 0119 /** 0120 * @brief getChannels 0121 * get used channels 0122 * @return 0123 */ 0124 QVector <int> getChannels() const; 0125 0126 /** 0127 * @brief setCursorPosition 0128 * Set the cursor to normalized shape coordinates. This will only repaint the cursor. 0129 * @param position normalized shape coordinates ([0,1] range, not yet transformed to actual channel values!) 0130 * @param signal if true, emit a sigCursorMoved signal 0131 */ 0132 void setCursorPosition(QPointF position, bool signal = false); 0133 0134 /** 0135 * @brief setChannelValues 0136 * Set the current channel values; 0137 * Note that channel values controlled by the shape itself have no effect unless setCursor is true. 0138 * This will trigger a full widget repaint. 0139 * @param position normalized shape coordinates ([0,1] range) 0140 * these are not yet transformed to color space specific ranges! 0141 * @param setCursor if true, sets the cursor too, otherwise the shape-controlled channels are not set 0142 */ 0143 void setChannelValues(QVector4D channelValues, bool setCursor); 0144 0145 void setAcceptTabletEvents(bool on); 0146 0147 Q_SIGNALS: 0148 void sigCursorMoved(QPointF pos); 0149 0150 public Q_SLOTS: 0151 /** 0152 * @brief slotSetActiveChannels 0153 * Change the active channels if necessary. 0154 * @param channel1 used by single and twodimensional widgets. 0155 * @param channel2 only used by twodimensional widgets. 0156 */ 0157 void slotSetActiveChannels(int channel1, int channel2); 0158 0159 protected: 0160 /** 0161 * @brief convertImageMap 0162 * convert image data containing raw KoColor data into a QImage 0163 * @param data must point to memory of size width()*height()*pixelSize 0164 * @param size the number of bytes to read from data, must match aforementioned cirteria 0165 * @return the converted QImage guaranteed to match the widget size (black content on failure) 0166 */ 0167 QImage convertImageMap(const quint8 *rawColor, quint32 bufferSize, QSize imgSize) const; 0168 /** 0169 * @brief renderBackground 0170 * Render the widget background visible inside the widget's mask in current color space 0171 * Rendering shall be done with the conversion functions of KisVisualColorSelector 0172 * @param data points to zero-initialized memory of size width()*height()*pixelSize 0173 * @param pixelSize the data size to transfer from KoColor::data() to data per pixel 0174 * in the current color space 0175 * @param channelValues the normalized channel values of the currently selected color 0176 */ 0177 virtual QImage renderBackground(const QVector4D &channelValues, quint32 pixelSize) const; 0178 /** 0179 * @brief render the alpha mask for the widget background 0180 * the returned image is expected to be QImage::Format_Alpha8 0181 */ 0182 virtual QImage renderAlphaMask() const; 0183 /** 0184 * @brief default implementation just calls convertWidgetCoordinateToShapeCoordinate(pos) 0185 */ 0186 virtual QPointF mousePositionToShapeCoordinate(const QPointF &pos, const QPointF &dragStart) const; 0187 0188 void mousePressEvent(QMouseEvent *e) override; 0189 void mouseMoveEvent(QMouseEvent *e) override; 0190 void mouseReleaseEvent(QMouseEvent *e) override; 0191 void tabletEvent(QTabletEvent* event) override; 0192 void paintEvent(QPaintEvent*) override; 0193 void resizeEvent(QResizeEvent *) override; 0194 0195 private: 0196 struct Private; 0197 const QScopedPointer<Private> m_d; 0198 0199 /** 0200 * @brief convertShapeCoordinateToWidgetCoordinate 0201 * @return take the position in the shape and convert it to screen coordinates. 0202 */ 0203 virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF) const = 0; 0204 0205 /** 0206 * @brief convertWidgetCoordinateToShapeCoordinate 0207 * Convert a coordinate in the widget's height/width to a shape coordinate. 0208 * @param coordinate the position your wish to have the shape coordinates of. 0209 */ 0210 virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPointF coordinate) const = 0; 0211 0212 /** 0213 * @brief getPixmap 0214 * @return the pixmap of this shape. 0215 */ 0216 virtual QRegion getMaskMap() = 0; 0217 virtual void drawCursor() = 0; 0218 }; 0219 0220 #endif