File indexing completed on 2024-05-12 15:58:40

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef KIS_SELECTION_H_
0007 #define KIS_SELECTION_H_
0008 
0009 #include <QRect>
0010 
0011 #include "kis_types.h"
0012 #include "kritaimage_export.h"
0013 #include "kis_default_bounds.h"
0014 #include "kis_image.h"
0015 
0016 #include "KisSelectionTags.h"
0017 
0018 #include "kis_pixel_selection.h"
0019 
0020 
0021 class KisSelectionComponent;
0022 class QPainterPath;
0023 
0024 /**
0025  * KisSelection is a composite object. It may contain an instance
0026  * of KisPixelSelection and a KisShapeSelection object. Both these
0027  * selections are merged into a projection of the KisSelection.
0028  *
0029  * Every pixel in the paint device can indicate a degree of selectedness, varying
0030  * between MIN_SELECTED and MAX_SELECTED.
0031  *
0032  * The projection() paint device itself is only a projection: you can
0033  * read from it, but not write to it. You need to keep track of
0034  * the need for updating the projection yourself: there is no
0035  * automatic updating after changing the contents of one or more
0036  * of the selection components.
0037  */
0038 class KRITAIMAGE_EXPORT KisSelection : public KisShared
0039 {
0040 private:
0041     struct ChangeShapeSelectionCommand;
0042 
0043 public:
0044     /**
0045      * Create a new KisSelection.
0046      *
0047      * @param defaultBounds defines the bounds of the selection when
0048      * Select All is initiated.
0049      */
0050     KisSelection(KisDefaultBoundsBaseSP defaultBounds = KisDefaultBoundsBaseSP());
0051 
0052     /**
0053      * Copy the selection. The selection components are copied, too.
0054      */
0055     KisSelection(const KisSelection& rhs);
0056     KisSelection& operator=(const KisSelection &rhs);
0057 
0058     /**
0059      * Delete the selection. The shape selection component is deleted, the
0060      * pixel selection component is contained in a shared pointer, so that
0061      * may still be valid.
0062      */
0063     virtual ~KisSelection();
0064 
0065     /**
0066      * Create a new selection using the content of copySource as the mask.
0067      */
0068     KisSelection(const KisPaintDeviceSP copySource, KritaUtils::DeviceCopyMode copyMode, KisDefaultBoundsBaseSP defaultBounds);
0069 
0070     /**
0071      * The paint device of the pixel selection should report
0072      * about it's setDirty events to its parent. The creator
0073      * should set the parent manually if it wants to get the
0074      * signals
0075      */
0076     void setParentNode(KisNodeWSP node);
0077 
0078     bool hasNonEmptyPixelSelection() const;
0079     bool hasNonEmptyShapeSelection() const;
0080     bool hasShapeSelection() const;
0081 
0082     bool outlineCacheValid() const;
0083     QPainterPath outlineCache() const;
0084     void recalculateOutlineCache();
0085 
0086 
0087     /**
0088      * Tells whether the cached thumbnail of the selection is still valid
0089      */
0090     bool thumbnailImageValid() const;
0091 
0092     /**
0093      * Recalculates the thumbnail of the selection
0094      */
0095     void recalculateThumbnailImage(const QColor &maskColor);
0096 
0097     /**
0098      * Returns the thumbnail of the selection.
0099      */
0100     QImage thumbnailImage() const;
0101 
0102     /**
0103      * Returns the transformation which should be applied to the thumbnail before
0104      * being painted over the image
0105      */
0106     QTransform thumbnailImageTransform() const;
0107 
0108 
0109     /**
0110      * return the pixel selection component of this selection. Pixel
0111      * selection component is always present in the selection. In case
0112      * the user wants a vector selection, pixel selection will store
0113      * the pixelated version of it.
0114      *
0115      * NOTE: use pixelSelection() for changing the selection only. For
0116      * reading the selection and passing the data to bitBlt function use
0117      * projection(). Although projection() and pixelSelection() currently
0118      * point ot the same paint device, this behavior may change in the
0119      * future.
0120      */
0121     KisPixelSelectionSP pixelSelection() const;
0122 
0123     /**
0124      * return the vector selection component of this selection or zero
0125      * if hasShapeSelection() returns false.
0126      */
0127     KisSelectionComponent* shapeSelection() const;
0128 
0129     /**
0130      * @brief converts shape selection into the vector state
0131      *
0132      * The selection must not have any shape selection active. It should
0133      * be checked by calling hasShapeSelection() in advance.
0134      *
0135      * @param shapeSelection new shape selection object that should be
0136      *                       attached to the selection
0137      * @return undo command that exectes and undos the conversion
0138      */
0139     KUndo2Command* convertToVectorSelection(KisSelectionComponent* shapeSelection);
0140 
0141     /**
0142      * @see convertToVectorSelection()
0143      */
0144     void convertToVectorSelectionNoUndo(KisSelectionComponent* shapeSelection);
0145 
0146     /**
0147      * Returns the projection of the selection. It may be the same
0148      * as pixel selection. You must read selection data from this
0149      * paint device only
0150      */
0151     KisPixelSelectionSP projection() const;
0152 
0153     /**
0154      * Updates the projection of the selection. You should call this
0155      * method after the every change of the selection components.
0156      * There is no automatic updates framework present
0157      */
0158     void updateProjection(const QRect& rect);
0159     void updateProjection();
0160 
0161     void setVisible(bool visible);
0162     bool isVisible();
0163 
0164     /**
0165      * Convenience functions. Just call the corresponding methods
0166      * of the underlying projection
0167      */
0168     bool isTotallyUnselected(const QRect & r) const;
0169 
0170     QRect selectedRect() const;
0171 
0172     /**
0173      * @brief Slow, but exact way of determining the rectangle
0174      * that encloses the selection.
0175      *
0176      * Default pixel of the selection device may vary and you would get wrong bounds.
0177      * selectedExactRect() handles all these cases.
0178      *
0179      */
0180     QRect selectedExactRect() const;
0181 
0182     void setX(qint32 x);
0183     void setY(qint32 y);
0184 
0185     qint32 x() const;
0186     qint32 y() const;
0187 
0188     void setDefaultBounds(KisDefaultBoundsBaseSP bounds);
0189 
0190     void clear();
0191 
0192     /**
0193      * @brief flatten creates a new pixel selection component from the shape selection
0194      * and throws away the shape selection. This has no effect if there is no
0195      * shape selection.
0196      */
0197     KUndo2Command* flatten();
0198 
0199     void notifySelectionChanged();
0200 
0201     /**
0202      * Request rerendering of the shape selection component in a
0203      * compressed way. Usually, you don't need to call it manually,
0204      * because all the work is done by KisShapeSelectionModel.
0205      */
0206     void requestCompressedProjectionUpdate(const QRect &rc);
0207 
0208     /// XXX: This method was marked KDE_DEPRECATED but without information on what to
0209     /// replace it with. Undeprecate, therefore.
0210     quint8 selected(qint32 x, qint32 y) const;
0211 
0212     KisNodeWSP parentNode() const;
0213 
0214 private:
0215     friend class KisSelectionTest;
0216     friend class KisMaskTest;
0217     friend class KisAdjustmentLayerTest;
0218     friend class KisUpdateSelectionJob;
0219     friend class KisSelectionUpdateCompressor;
0220     friend class KisDeselectActiveSelectionCommand;
0221 
0222     void copyFrom(const KisSelection &rhs);
0223 
0224 private:
0225 
0226     struct Private;
0227     Private * const m_d;
0228 };
0229 
0230 #endif // KIS_SELECTION_H_