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