File indexing completed on 2024-06-23 04:28:32

0001 /*
0002  *  tool_transform_args.h - part of Krita
0003  *
0004  *  SPDX-FileCopyrightText: 2010 Marc Pegon <pe.marc@free.fr>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef TOOL_TRANSFORM_ARGS_H_
0010 #define TOOL_TRANSFORM_ARGS_H_
0011 
0012 #include <QPointF>
0013 #include <QVector3D>
0014 #include <kis_warptransform_worker.h>
0015 #include <kis_filter_strategy.h>
0016 #include "kis_liquify_properties.h"
0017 #include "kritatooltransform_export.h"
0018 #include "kis_global.h"
0019 #include "KisToolChangesTrackerData.h"
0020 #include "KisBezierTransformMesh.h"
0021 #include "kis_paint_device.h"
0022 
0023 #include <QScopedPointer>
0024 class KisLiquifyTransformWorker;
0025 class QDomElement;
0026 
0027 /**
0028  * Class used to store the parameters of a transformation.
0029  * Some parameters are specific to free transform mode, and
0030  * others to warp mode : maybe add a union to save a little more
0031  * memory.
0032  */
0033 
0034 class KRITATOOLTRANSFORM_EXPORT ToolTransformArgs : public KisToolChangesTrackerData
0035 {
0036 public:
0037     enum TransformMode {FREE_TRANSFORM = 0,
0038                         WARP,
0039                         CAGE,
0040                         LIQUIFY,
0041                         PERSPECTIVE_4POINT,
0042                         MESH,
0043                         N_MODES};
0044 
0045     /**
0046      * Initializes the parameters for an identity transformation,
0047      * with mode set to free transform.
0048      */
0049     ToolTransformArgs();
0050 
0051     /**
0052      * The object return will be a copy of args.
0053      */
0054     ToolTransformArgs(const ToolTransformArgs& args);
0055 
0056     KisToolChangesTrackerData *clone() const override;
0057 
0058     /**
0059      * If mode is warp, original and transformed vector points will be of size 0.
0060      * Use setPoints method to set those vectors.
0061      */
0062     ToolTransformArgs(TransformMode mode,
0063                       QPointF transformedCenter,
0064                       QPointF originalCenter,
0065                       QPointF rotationCenterOffset, bool transformAroundRotationCenter,
0066                       double aX, double aY, double aZ,
0067                       double scaleX, double scaleY,
0068                       double shearX, double shearY,
0069                       KisWarpTransformWorker::WarpType warpType,
0070                       double alpha,
0071                       bool defaultPoints,
0072                       const QString &filterId,
0073                       int pixelPrecision, int previewPixelPrecision,
0074                       KisPaintDeviceSP externalSource);
0075     ~ToolTransformArgs();
0076     ToolTransformArgs& operator=(const ToolTransformArgs& args);
0077 
0078     bool operator==(const ToolTransformArgs& other) const;
0079     bool isSameMode(const ToolTransformArgs& other) const;
0080 
0081     inline TransformMode mode() const {
0082         return m_mode;
0083     }
0084     inline void setMode(TransformMode mode) {
0085         m_mode = mode;
0086     }
0087 
0088     inline int pixelPrecision() const {
0089         return m_pixelPrecision;
0090     }
0091 
0092     inline void setPixelPrecision(int precision) {
0093         m_pixelPrecision = precision;
0094     }
0095 
0096     inline int previewPixelPrecision() const {
0097         return m_previewPixelPrecision;
0098     }
0099 
0100     inline void setPreviewPixelPrecision(int precision) {
0101         m_previewPixelPrecision = precision;
0102     }
0103 
0104     inline KisPaintDeviceSP externalSource() const {
0105         return m_externalSource;
0106     }
0107 
0108     inline void setExternalSource(KisPaintDeviceSP externalSource) {
0109         m_externalSource = externalSource;
0110     }
0111 
0112     //warp-related
0113     inline int numPoints() const {
0114         KIS_ASSERT_RECOVER_NOOP(m_origPoints.size() == m_transfPoints.size());
0115         return m_origPoints.size();
0116     }
0117     inline QPointF &origPoint(int i) {
0118         return m_origPoints[i];
0119     }
0120     inline QPointF &transfPoint(int i) {
0121         return m_transfPoints[i];
0122     }
0123     inline const QVector<QPointF> &origPoints() const {
0124         return m_origPoints;
0125     }
0126     inline const QVector<QPointF> &transfPoints() const {
0127         return m_transfPoints;
0128     }
0129 
0130     inline QVector<QPointF> &refOriginalPoints() {
0131         return m_origPoints;
0132     }
0133     inline QVector<QPointF> &refTransformedPoints() {
0134         return m_transfPoints;
0135     }
0136 
0137     inline KisWarpTransformWorker::WarpType warpType() const {
0138         return m_warpType;
0139     }
0140     inline double alpha() const {
0141         return m_alpha;
0142     }
0143     inline bool defaultPoints() const {
0144         return m_defaultPoints;
0145     }
0146     inline void setPoints(QVector<QPointF> origPoints, QVector<QPointF> transfPoints) {
0147         m_origPoints = QVector<QPointF>(origPoints);
0148         m_transfPoints = QVector<QPointF>(transfPoints);
0149     }
0150     inline void setWarpType(KisWarpTransformWorker::WarpType warpType) {
0151         m_warpType = warpType;
0152     }
0153     inline void setWarpCalculation(KisWarpTransformWorker::WarpCalculation warpCalc) {
0154         m_warpCalculation = warpCalc;
0155     }
0156     inline KisWarpTransformWorker::WarpCalculation warpCalculation() {
0157         return m_warpCalculation;
0158     }
0159 
0160     inline void setAlpha(double alpha) {
0161         m_alpha = alpha;
0162     }
0163     inline void setDefaultPoints(bool defaultPoints) {
0164         m_defaultPoints = defaultPoints;
0165     }
0166 
0167     //"free transform"-related
0168     inline QPointF transformedCenter() const {
0169         return m_transformedCenter;
0170     }
0171     inline QPointF originalCenter() const {
0172         return m_originalCenter;
0173     }
0174     inline QPointF rotationCenterOffset() const {
0175         return m_rotationCenterOffset;
0176     }
0177     inline bool transformAroundRotationCenter() const {
0178         return m_transformAroundRotationCenter;
0179     }
0180     inline double aX() const {
0181         return m_aX;
0182     }
0183     inline double aY() const {
0184         return m_aY;
0185     }
0186     inline double aZ() const {
0187         return m_aZ;
0188     }
0189     inline QVector3D cameraPos() const {
0190         return m_cameraPos;
0191     }
0192     inline double scaleX() const {
0193         return m_scaleX;
0194     }
0195     inline double scaleY() const {
0196         return m_scaleY;
0197     }
0198     inline bool keepAspectRatio() const {
0199         return m_keepAspectRatio;
0200     }
0201     inline double shearX() const {
0202         return m_shearX;
0203     }
0204     inline double shearY() const {
0205         return m_shearY;
0206     }
0207 
0208     inline void setTransformedCenter(QPointF transformedCenter) {
0209         m_transformedCenter = transformedCenter;
0210     }
0211     inline void setOriginalCenter(QPointF originalCenter) {
0212         m_originalCenter = originalCenter;
0213     }
0214     inline void setRotationCenterOffset(QPointF rotationCenterOffset) {
0215         m_rotationCenterOffset = rotationCenterOffset;
0216     }
0217     void setTransformAroundRotationCenter(bool value);
0218 
0219     inline void setAX(double aX) {
0220         m_aX = aX;
0221     }
0222     inline void setAY(double aY) {
0223         m_aY = aY;
0224     }
0225     inline void setAZ(double aZ) {
0226         m_aZ = aZ;
0227     }
0228     inline void setCameraPos(const QVector3D &pos) {
0229         m_cameraPos = pos;
0230     }
0231     inline void setScaleX(double scaleX) {
0232         m_scaleX = scaleX;
0233     }
0234     inline void setScaleY(double scaleY) {
0235         m_scaleY = scaleY;
0236     }
0237     inline void setKeepAspectRatio(bool value) {
0238         m_keepAspectRatio = value;
0239     }
0240     inline void setShearX(double shearX) {
0241         m_shearX = shearX;
0242     }
0243     inline void setShearY(double shearY) {
0244         m_shearY = shearY;
0245     }
0246 
0247     inline QString filterId() const {
0248         return m_filter->id();
0249     }
0250 
0251     void setFilterId(const QString &id);
0252 
0253     inline KisFilterStrategy* filter() const {
0254         return m_filter;
0255     }
0256 
0257     // True if the transformation does not differ from the initial one. The
0258     // target device may still need changing if we are placing an external source.
0259     bool isIdentity() const;
0260 
0261     // True if the target device does not need changing as a result of this
0262     // transformation, because the transformation does not differ from the initial
0263     // one and the source image is not external.
0264     bool isUnchanging() const;
0265 
0266     inline QTransform flattenedPerspectiveTransform() const {
0267         return m_flattenedPerspectiveTransform;
0268     }
0269 
0270     inline void setFlattenedPerspectiveTransform(const QTransform &value) {
0271         m_flattenedPerspectiveTransform = value;
0272     }
0273 
0274     bool isEditingTransformPoints() const {
0275         return m_editTransformPoints;
0276     }
0277 
0278     void setEditingTransformPoints(bool value) {
0279         m_editTransformPoints = value;
0280     }
0281 
0282     const KisLiquifyProperties* liquifyProperties() const {
0283         return m_liquifyProperties.data();
0284     }
0285 
0286     KisLiquifyProperties* liquifyProperties() {
0287         return m_liquifyProperties.data();
0288     }
0289 
0290     void initLiquifyTransformMode(const QRect &srcRect);
0291     void saveLiquifyTransformMode() const;
0292 
0293     KisLiquifyTransformWorker* liquifyWorker() const {
0294         return m_liquifyWorker.data();
0295     }
0296 
0297     void toXML(QDomElement *e) const;
0298     static ToolTransformArgs fromXML(const QDomElement &e);
0299 
0300     void translateSrcAndDst(const QPointF &offset);
0301     void transformSrcAndDst(const QTransform &t);
0302     void translateDstSpace(const QPointF &offset);
0303 
0304     void saveContinuedState();
0305     void restoreContinuedState();
0306     const ToolTransformArgs* continuedTransform() const;
0307 
0308     const KisBezierTransformMesh* meshTransform() const;
0309     KisBezierTransformMesh* meshTransform();
0310 
0311     bool meshShowHandles() const;
0312     void setMeshShowHandles(bool value);
0313 
0314     bool meshSymmetricalHandles() const;
0315     void setMeshSymmetricalHandles(bool meshSymmetricalHandles);
0316 
0317     bool meshScaleHandles() const;
0318     void setMeshScaleHandles(bool meshScaleHandles);
0319 
0320     void scale3dSrcAndDst(qreal scale);
0321 
0322 private:
0323     void clear();
0324     void init(const ToolTransformArgs& args);
0325     TransformMode m_mode {ToolTransformArgs::TransformMode::FREE_TRANSFORM};
0326 
0327     // warp-related arguments
0328     // these are basically the arguments taken by the warp transform worker
0329     bool m_defaultPoints {true}; // true : the original points are set to make a grid
0330                           // which density is given by numPoints()
0331     QVector<QPointF> m_origPoints;
0332     QVector<QPointF> m_transfPoints;
0333     KisWarpTransformWorker::WarpType m_warpType {KisWarpTransformWorker::WarpType_::RIGID_TRANSFORM};
0334     KisWarpTransformWorker::WarpCalculation m_warpCalculation {KisWarpTransformWorker::WarpCalculation::DRAW}; // DRAW or GRID
0335     double m_alpha {1.0};
0336 
0337     //'free transform'-related
0338     // basically the arguments taken by the transform worker
0339     QPointF m_transformedCenter;
0340     QPointF m_originalCenter;
0341     QPointF m_rotationCenterOffset; // the position of the rotation center relative to
0342                                     // the original top left corner of the selection
0343                                     // before any transformation
0344     bool m_transformAroundRotationCenter {false}; // In freehand mode makes the scaling and other transformations
0345                                           // be anchored to the rotation center point.
0346 
0347     double m_aX {0};
0348     double m_aY {0};
0349     double m_aZ {0};
0350     QVector3D m_cameraPos {QVector3D(0,0,1024)};
0351     double m_scaleX {1.0};
0352     double m_scaleY {1.0};
0353     double m_shearX {0.0};
0354     double m_shearY {0.0};
0355     bool m_keepAspectRatio {false};
0356 
0357     // perspective transform related
0358     QTransform m_flattenedPerspectiveTransform;
0359 
0360     KisFilterStrategy *m_filter {0};
0361     bool m_editTransformPoints {false};
0362     QSharedPointer<KisLiquifyProperties> m_liquifyProperties;
0363     QScopedPointer<KisLiquifyTransformWorker> m_liquifyWorker;
0364 
0365     KisBezierTransformMesh m_meshTransform;
0366     bool m_meshShowHandles = true;
0367     bool m_meshSymmetricalHandles = true;
0368     bool m_meshScaleHandles = false;
0369 
0370     /**
0371      * When we continue a transformation, m_continuedTransformation
0372      * stores the initial step of our transform. All cancel and revert
0373      * operations should revert to it.
0374      */
0375     QScopedPointer<ToolTransformArgs> m_continuedTransformation;
0376 
0377     //PixelPrecision should always be in powers of 2
0378     int m_pixelPrecision {8};
0379     int m_previewPixelPrecision {16};
0380 
0381     /**
0382      * Optional external image, for example from the clipboard, that
0383      * can be transformed directly over an existing paint layer or mask.
0384      */
0385     KisPaintDeviceSP m_externalSource;
0386 };
0387 
0388 #endif // TOOL_TRANSFORM_ARGS_H_