File indexing completed on 2024-05-12 15:58:25
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_LAYER_UTILS_H 0008 #define __KIS_LAYER_UTILS_H 0009 0010 #include <functional> 0011 0012 #include "kundo2command.h" 0013 #include "kis_types.h" 0014 #include "kritaimage_export.h" 0015 #include "kis_command_utils.h" 0016 #include "kis_time_span.h" 0017 #include "kis_image.h" 0018 0019 class KoProperties; 0020 class KoColor; 0021 class QUuid; 0022 0023 namespace KisMetaData 0024 { 0025 class MergeStrategy; 0026 } 0027 0028 namespace KisLayerUtils 0029 { 0030 KRITAIMAGE_EXPORT void sortMergableNodes(KisNodeSP root, QList<KisNodeSP> &inputNodes, QList<KisNodeSP> &outputNodes); 0031 KRITAIMAGE_EXPORT KisNodeList sortMergableNodes(KisNodeSP root, KisNodeList nodes); 0032 KRITAIMAGE_EXPORT void filterMergableNodes(KisNodeList &nodes, bool allowMasks = false); 0033 KRITAIMAGE_EXPORT KisNodeList sortAndFilterAnyMergableNodesSafe(const KisNodeList &nodes, KisImageSP image); 0034 KRITAIMAGE_EXPORT bool checkIsChildOf(KisNodeSP node, const KisNodeList &parents); 0035 KRITAIMAGE_EXPORT void filterUnlockedNodes(KisNodeList &nodes); 0036 KRITAIMAGE_EXPORT void refreshHiddenAreaAsync(KisImageSP image, KisNodeSP rootNode, const QRect &preparedArea); 0037 KRITAIMAGE_EXPORT QRect recursiveTightNodeVisibleBounds(KisNodeSP rootNode); 0038 0039 /** 0040 * Returns true if: 0041 * o \p node is a clone of some layer in \p nodes 0042 * o \p node is a clone any child layer of any layer in \p nodes 0043 * o \p node is a clone of a clone of a ..., that in the end points 0044 * to any layer in \p nodes of their children. 0045 */ 0046 KRITAIMAGE_EXPORT bool checkIsCloneOf(KisNodeSP node, const KisNodeList &nodes); 0047 KRITAIMAGE_EXPORT void forceAllDelayedNodesUpdate(KisNodeSP root); 0048 KRITAIMAGE_EXPORT bool hasDelayedNodeWithUpdates(KisNodeSP root); 0049 0050 KRITAIMAGE_EXPORT void forceAllHiddenOriginalsUpdate(KisNodeSP root); 0051 0052 KRITAIMAGE_EXPORT KisNodeList sortAndFilterMergableInternalNodes(KisNodeList nodes, bool allowMasks = false); 0053 0054 KRITAIMAGE_EXPORT void mergeDown(KisImageSP image, KisLayerSP layer, const KisMetaData::MergeStrategy* strategy); 0055 0056 KRITAIMAGE_EXPORT QSet<int> fetchLayerFrames(KisNodeSP node); 0057 KRITAIMAGE_EXPORT QSet<int> fetchLayerFramesRecursive(KisNodeSP rootNode); 0058 0059 KRITAIMAGE_EXPORT void mergeMultipleLayers(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter); 0060 KRITAIMAGE_EXPORT void newLayerFromVisible(KisImageSP image, KisNodeSP putAfter); 0061 0062 KRITAIMAGE_EXPORT bool tryMergeSelectionMasks(KisImageSP image, KisNodeList mergedNodes, KisNodeSP putAfter); 0063 0064 KRITAIMAGE_EXPORT void flattenLayer(KisImageSP image, KisLayerSP layer); 0065 KRITAIMAGE_EXPORT void flattenImage(KisImageSP image, KisNodeSP activeNode); 0066 0067 KRITAIMAGE_EXPORT void addCopyOfNameTag(KisNodeSP node); 0068 KRITAIMAGE_EXPORT KisNodeList findNodesWithProps(KisNodeSP root, const KoProperties &props, bool excludeRoot); 0069 0070 KRITAIMAGE_EXPORT void changeImageDefaultProjectionColor(KisImageSP image, const KoColor &color); 0071 0072 KRITAIMAGE_EXPORT KisNodeSP findRoot(KisNodeSP node); 0073 0074 KRITAIMAGE_EXPORT bool canChangeImageProfileInvisibly(KisImageSP image); 0075 0076 KRITAIMAGE_EXPORT void splitAlphaToMask(KisImageSP image, KisNodeSP node, const QString& maskName); 0077 0078 KRITAIMAGE_EXPORT void convertToPaintLayer(KisImageSP image, KisNodeSP src); 0079 0080 typedef QMap<int, QSet<KisNodeSP> > FrameJobs; 0081 void updateFrameJobs(FrameJobs *jobs, KisNodeSP node); 0082 void updateFrameJobsRecursive(FrameJobs *jobs, KisNodeSP rootNode); 0083 0084 /** 0085 * @brief The SwitchFrameCommand struct 0086 * Switches to frame with undo/redo support. 0087 */ 0088 struct KRITAIMAGE_EXPORT SwitchFrameCommand : public KisCommandUtils::FlipFlopCommand { 0089 struct KRITAIMAGE_EXPORT SharedStorage { 0090 /** 0091 * For some reason the absence of a destructor in the SharedStorage 0092 * makes Krita crash on exit. Seems like some compiler weirdness... (DK) 0093 */ 0094 ~SharedStorage(); 0095 int value; 0096 }; 0097 0098 typedef QSharedPointer<SharedStorage> SharedStorageSP; 0099 0100 public: 0101 SwitchFrameCommand(KisImageSP image, int time, bool finalize, SharedStorageSP storage); 0102 ~SwitchFrameCommand() override; 0103 0104 private: 0105 void partA() override; 0106 void partB() override; 0107 0108 private: 0109 KisImageWSP m_image; 0110 int m_newTime; 0111 SharedStorageSP m_storage; 0112 }; 0113 0114 /** 0115 * A command to keep correct set of selected/active nodes thoroughout 0116 * the action. 0117 */ 0118 class KRITAIMAGE_EXPORT KeepNodesSelectedCommand : public KisCommandUtils::FlipFlopCommand 0119 { 0120 public: 0121 KeepNodesSelectedCommand(const KisNodeList &selectedBefore, 0122 const KisNodeList &selectedAfter, 0123 KisNodeSP activeBefore, 0124 KisNodeSP activeAfter, 0125 KisImageSP image, 0126 bool finalize, KUndo2Command *parent = 0); 0127 void partB() override; 0128 0129 private: 0130 KisNodeList m_selectedBefore; 0131 KisNodeList m_selectedAfter; 0132 KisNodeSP m_activeBefore; 0133 KisNodeSP m_activeAfter; 0134 KisImageWSP m_image; 0135 }; 0136 0137 struct KRITAIMAGE_EXPORT SelectGlobalSelectionMask : public KUndo2Command 0138 { 0139 public: 0140 SelectGlobalSelectionMask(KisImageSP image); 0141 ~SelectGlobalSelectionMask(); 0142 void redo() override; 0143 0144 private: 0145 KisImageSP m_image; 0146 }; 0147 0148 class KRITAIMAGE_EXPORT RemoveNodeHelper { 0149 public: 0150 virtual ~RemoveNodeHelper(); 0151 protected: 0152 virtual void addCommandImpl(KUndo2Command *cmd) = 0; 0153 void safeRemoveMultipleNodes(KisNodeList nodes, KisImageSP image); 0154 private: 0155 bool checkIsSourceForClone(KisNodeSP src, const KisNodeList &nodes); 0156 static bool scanForLastLayer(KisImageWSP image, KisNodeList nodesToRemove); 0157 }; 0158 0159 struct KRITAIMAGE_EXPORT SimpleRemoveLayers : private KisLayerUtils::RemoveNodeHelper, public KisCommandUtils::AggregateCommand { 0160 SimpleRemoveLayers(const KisNodeList &nodes, 0161 KisImageSP image); 0162 0163 void populateChildCommands() override; 0164 0165 protected: 0166 void addCommandImpl(KUndo2Command *cmd) override; 0167 0168 private: 0169 KisNodeList m_nodes; 0170 KisImageSP m_image; 0171 KisNodeList m_selectedNodes; 0172 KisNodeSP m_activeNode; 0173 }; 0174 0175 class KRITAIMAGE_EXPORT KisSimpleUpdateCommand : public KisCommandUtils::FlipFlopCommand 0176 { 0177 public: 0178 KisSimpleUpdateCommand(KisNodeList nodes, bool finalize, KUndo2Command *parent = 0); 0179 void partB() override; 0180 static void updateNodes(const KisNodeList &nodes); 0181 private: 0182 KisNodeList m_nodes; 0183 }; 0184 0185 template <typename T> 0186 bool checkNodesDiffer(KisNodeList nodes, std::function<T(KisNodeSP)> checkerFunc) 0187 { 0188 bool valueDiffers = false; 0189 bool initialized = false; 0190 T currentValue = T(); 0191 Q_FOREACH (KisNodeSP node, nodes) { 0192 if (!initialized) { 0193 currentValue = checkerFunc(node); 0194 initialized = true; 0195 } else if (currentValue != checkerFunc(node)) { 0196 valueDiffers = true; 0197 break; 0198 } 0199 } 0200 return valueDiffers; 0201 } 0202 0203 /** 0204 * Applies \p func to \p node and all its children recursively 0205 */ 0206 template <typename NodePointer, typename Functor> 0207 void recursiveApplyNodes(NodePointer node, Functor func) 0208 { 0209 func(node); 0210 0211 node = node->firstChild(); 0212 while (node) { 0213 recursiveApplyNodes(node, func); 0214 node = node->nextSibling(); 0215 } 0216 } 0217 0218 0219 /** 0220 * Walks through \p node and all its children recursively until 0221 * \p func returns true. When \p func returns true, the node is 0222 * considered to be found, the search is stopped and the found 0223 * node is returned to the caller. 0224 */ 0225 KRITAIMAGE_EXPORT KisNodeSP recursiveFindNode(KisNodeSP node, std::function<bool(KisNodeSP)> func); 0226 0227 /** 0228 * Recursively searches for a node with specified Uuid 0229 */ 0230 KRITAIMAGE_EXPORT KisNodeSP findNodeByUuid(KisNodeSP root, const QUuid &uuid); 0231 0232 KRITAIMAGE_EXPORT KisImageSP findImageByHierarchy(KisNodeSP node); 0233 0234 template <class T> 0235 T* findNodeByType(KisNodeSP root) { 0236 return dynamic_cast<T*>(recursiveFindNode(root, [] (KisNodeSP node) { 0237 return bool(dynamic_cast<T*>(node.data())); 0238 }).data()); 0239 } 0240 0241 // Methods used by filter manager, filter stroke strategy to get times associated with frameIDs. 0242 // Important for avoiding instanced frame data being processed twice! 0243 KRITAIMAGE_EXPORT int fetchLayerActiveRasterFrameTime(KisNodeSP node); 0244 KRITAIMAGE_EXPORT KisTimeSpan fetchLayerActiveRasterFrameSpan(KisNodeSP node, const int time); 0245 KRITAIMAGE_EXPORT QSet<int> fetchLayerIdenticalRasterFrameTimes(KisNodeSP node, const int& frameTime); 0246 0247 KRITAIMAGE_EXPORT QSet<int> filterTimesForOnlyRasterKeyedTimes(KisNodeSP node, const QSet<int> ×); 0248 0249 /* Returns a set of times associated with every unique frame from a selection. */ 0250 KRITAIMAGE_EXPORT QSet<int> fetchUniqueFrameTimes(KisNodeSP node, QSet<int> selectedTimes, bool filterActiveFrameID); 0251 } 0252 0253 #endif /* __KIS_LAYER_UTILS_H */