File indexing completed on 2024-06-16 04:18:02

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_TRANSFORM_UTILS_H
0008 #define __KIS_TRANSFORM_UTILS_H
0009 
0010 #include <QtGlobal>
0011 
0012 #include "kis_coordinates_converter.h"
0013 
0014 #include <QTransform>
0015 #include <QMatrix4x4>
0016 #include <kis_processing_visitor.h>
0017 #include <limits>
0018 
0019 // for kisSquareDistance only
0020 #include "kis_global.h"
0021 
0022 #include "tool_transform_args.h"
0023 
0024 class ToolTransformArgs;
0025 class KisTransformWorker;
0026 class TransformTransactionProperties;
0027 class KisSavedMacroCommand;
0028 class KisStrokeUndoFacade;
0029 class KisStrokeJobData;
0030 
0031 class KisTransformUtils
0032 {
0033 public:
0034 
0035     static const int rotationHandleVisualRadius;
0036     static const int handleVisualRadius;
0037     static const int handleRadius;
0038     static const int rotationHandleRadius;
0039 
0040     template <class T>
0041     static T flakeToImage(const KisCoordinatesConverter *converter, T object) {
0042         return converter->documentToImage(converter->flakeToDocument(object));
0043     }
0044 
0045     template <class T>
0046     static T imageToFlake(const KisCoordinatesConverter *converter, T object) {
0047         return converter->documentToFlake(converter->imageToDocument(object));
0048     }
0049 
0050     static QTransform imageToFlakeTransform(const KisCoordinatesConverter *converter);
0051     static qreal effectiveHandleGrabRadius(const KisCoordinatesConverter *converter);
0052 
0053     static qreal effectiveRotationHandleGrabRadius(const KisCoordinatesConverter *converter);
0054 
0055     static qreal scaleFromAffineMatrix(const QTransform &t);
0056     static qreal scaleFromPerspectiveMatrixX(const QTransform &t, const QPointF &basePt);
0057     static qreal scaleFromPerspectiveMatrixY(const QTransform &t, const QPointF &basePt);
0058     static qreal effectiveSize(const QRectF &rc);
0059     static bool thumbnailTooSmall(const QTransform &resultThumbTransform, const QRect &originalImageRect);
0060 
0061     static QRectF handleRect(qreal radius, const QTransform &t, const QRectF &limitingRect, qreal *dOutX, qreal *dOutY);
0062     static QRectF handleRect(qreal radius, const QTransform &t, const QRectF &limitingRect, const QPointF &basePoint);
0063 
0064     static QPointF clipInRect(QPointF p, QRectF r);
0065 
0066     struct MatricesPack
0067     {
0068         MatricesPack(const ToolTransformArgs &args);
0069 
0070         QTransform TS;
0071         QTransform SC;
0072         QTransform S;
0073         QMatrix4x4 P;
0074         QTransform projectedP;
0075         QTransform T;
0076 
0077         // the final transformation looks like
0078         // transform = TS * SC * S * projectedP * T
0079         QTransform finalTransform() const;
0080     };
0081 
0082     static bool checkImageTooBig(const QRectF &bounds, const MatricesPack &m, qreal cameraHeight);
0083 
0084     static KisTransformWorker createTransformWorker(const ToolTransformArgs &config,
0085                                                     KisPaintDeviceSP device,
0086                                                     KoUpdaterPtr updater,
0087                                                     QVector3D *transformedCenter /* OUT */);
0088 
0089     static void transformDevice(const ToolTransformArgs &config,
0090                                 KisPaintDeviceSP device,
0091                                 KisProcessingVisitor::ProgressHelper *helper);
0092 
0093     static void transformDevice(const ToolTransformArgs &config,
0094                                 KisPaintDeviceSP srcDevice,
0095                                 KisPaintDeviceSP dstDevice,
0096                                 KisProcessingVisitor::ProgressHelper *helper);
0097 
0098     static void transformDeviceWithCroppedDst(const ToolTransformArgs &config,
0099                                               KisPaintDeviceSP srcDevice,
0100                                               KisPaintDeviceSP dstDevice,
0101                                               KisProcessingVisitor::ProgressHelper *helper,
0102                                               bool forceSubPixelTranslation);
0103 
0104     static QRect needRect(const ToolTransformArgs &config,
0105                           const QRect &rc,
0106                           const QRect &srcBounds);
0107 
0108     static QRect changeRect(const ToolTransformArgs &config,
0109                             const QRect &rc);
0110 
0111     template<typename Function>
0112     class HandleChooser {
0113     public:
0114         HandleChooser(const QPointF &cursorPos, Function defaultFunction)
0115             : m_cursorPos(cursorPos),
0116               m_minDistance(std::numeric_limits<qreal>::max()),
0117               m_function(defaultFunction)
0118         {
0119         }
0120 
0121         bool addFunction(const QPointF &pt, qreal radius, Function function) {
0122             bool result = false;
0123             qreal distance = kisSquareDistance(pt, m_cursorPos);
0124 
0125             if (distance < pow2(radius) && distance < m_minDistance) {
0126                 m_minDistance = distance;
0127                 m_function = function;
0128                 result = true;
0129             }
0130 
0131             return result;
0132         }
0133 
0134         Function function() const {
0135             return m_function;
0136         }
0137 
0138     private:
0139         QPointF m_cursorPos;
0140         qreal m_minDistance;
0141         Function m_function;
0142     };
0143 
0144     /**
0145      * A special class that ensures that the view position of the anchor point of the
0146      * transformation is unchanged during the lifetime of the object. On destruction
0147      * of the keeper the position of the anchor point will be restored.
0148      */
0149     struct AnchorHolder {
0150         AnchorHolder(bool enabled, ToolTransformArgs *config);
0151         ~AnchorHolder();
0152 
0153     private:
0154         bool m_enabled;
0155         ToolTransformArgs *m_config;
0156         QPointF m_staticPoint;
0157         QPointF m_oldStaticPointInView;
0158 
0159     };
0160 
0161     static void setDefaultWarpPoints(int pointsPerLine,
0162                                      const TransformTransactionProperties *transaction,
0163                                      ToolTransformArgs *config);
0164 
0165     static ToolTransformArgs resetArgsForMode(ToolTransformArgs::TransformMode mode,
0166                                               const QString &filterId,
0167                                               const TransformTransactionProperties &transaction, KisPaintDeviceSP externalSource);
0168 
0169     static bool shouldRestartStrokeOnModeChange(ToolTransformArgs::TransformMode oldMode,
0170                                                 ToolTransformArgs::TransformMode newMode,
0171                                                 KisNodeList processedNodes);
0172 
0173     static void transformAndMergeDevice(const ToolTransformArgs &config,
0174                                         KisPaintDeviceSP src,
0175                                         KisPaintDeviceSP dst,
0176                                         KisProcessingVisitor::ProgressHelper *helper);
0177 
0178     static void postProcessToplevelCommand(KUndo2Command *command,
0179                                            const ToolTransformArgs &args,
0180                                            KisNodeList rootNodes,
0181                                            KisNodeList processedNodes, int currentTime,
0182                                            const KisSavedMacroCommand *overriddenCommand);
0183 
0184     static bool fetchArgsFromCommand(const KUndo2Command *command,
0185                                      ToolTransformArgs *args,
0186                                      KisNodeList *rootNodes,
0187                                      KisNodeList *transformedNodes, int *oldTime);
0188 
0189     static KisNodeSP tryOverrideRootToTransformMask(KisNodeSP root);
0190 
0191     static int fetchCurrentImageTime(KisNodeList rootNodes);
0192     static QList<KisNodeSP> fetchNodesList(ToolTransformArgs::TransformMode mode, KisNodeList rootNodes, bool isExternalSourcePresent, KisSelectionSP selection);
0193     static bool tryInitArgsFromNode(KisNodeList rootNodes, ToolTransformArgs *args);
0194     static bool tryFetchArgsFromCommandAndUndo(ToolTransformArgs *outArgs, ToolTransformArgs::TransformMode mode, KisNodeList currentNodes, KisNodeList selectedNodes, KisStrokeUndoFacade *undoFacade, int currentTime, QVector<KisStrokeJobData *> *undoJobs, const KisSavedMacroCommand **overriddenCommand);
0195 
0196 };
0197 
0198 #endif /* __KIS_TRANSFORM_UTILS_H */