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> &times);
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 */