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 */