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