File indexing completed on 2024-05-12 15:58:28
0001 /* 0002 * SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_merge_walker.h" 0008 #include "kis_projection_leaf.h" 0009 0010 0011 0012 KisMergeWalker::KisMergeWalker(QRect cropRect, Flags flags) 0013 : m_flags(flags) 0014 { 0015 setCropRect(cropRect); 0016 } 0017 0018 KisMergeWalker::~KisMergeWalker() 0019 { 0020 } 0021 0022 KisBaseRectsWalker::UpdateType KisMergeWalker::type() const 0023 { 0024 return m_flags == DEFAULT ? KisBaseRectsWalker::UPDATE : KisBaseRectsWalker::UPDATE_NO_FILTHY; 0025 } 0026 0027 void KisMergeWalker::startTripImpl(KisProjectionLeafSP startLeaf, KisMergeWalker::Flags flags) 0028 { 0029 if(startLeaf->isMask()) { 0030 startTripWithMask(startLeaf, flags); 0031 return; 0032 } 0033 0034 visitHigherNode(startLeaf, 0035 flags == DEFAULT ? N_FILTHY : N_ABOVE_FILTHY); 0036 0037 KisProjectionLeafSP prevLeaf = startLeaf->prevSibling(); 0038 if(prevLeaf) 0039 visitLowerNode(prevLeaf); 0040 } 0041 0042 0043 void KisMergeWalker::startTrip(KisProjectionLeafSP startLeaf) 0044 { 0045 startTripImpl(startLeaf, m_flags); 0046 } 0047 0048 void KisMergeWalker::startTripWithMask(KisProjectionLeafSP filthyMask, KisMergeWalker::Flags flags) 0049 { 0050 /** 0051 * Under very rare circumstances it may happen that the update 0052 * queue will contain a job pointing to a node that has 0053 * already been deleted from the image (directly or by undo 0054 * command). If it happens to a layer then the walker will 0055 * handle it as usual by building a trivial graph pointing to 0056 * nowhere, but when it happens to a mask... not. Because the 0057 * mask is always expected to have a parent layer to process. 0058 * 0059 * So just handle it here separately. 0060 */ 0061 KisProjectionLeafSP parentLayer = filthyMask->parent(); 0062 if (!parentLayer) { 0063 return; 0064 } 0065 0066 adjustMasksChangeRect(filthyMask); 0067 0068 KisProjectionLeafSP nextLeaf = parentLayer->nextSibling(); 0069 KisProjectionLeafSP prevLeaf = parentLayer->prevSibling(); 0070 0071 if (nextLeaf) 0072 visitHigherNode(nextLeaf, N_ABOVE_FILTHY); 0073 else if (parentLayer->parent()) 0074 startTripImpl(parentLayer->parent(), DEFAULT); 0075 0076 NodePosition positionToFilthy = 0077 (flags == DEFAULT ? N_FILTHY_PROJECTION : N_ABOVE_FILTHY) | 0078 calculateNodePosition(parentLayer); 0079 registerNeedRect(parentLayer, positionToFilthy); 0080 0081 if(prevLeaf) 0082 visitLowerNode(prevLeaf); 0083 } 0084 0085 void KisMergeWalker::visitHigherNode(KisProjectionLeafSP leaf, NodePosition positionToFilthy) 0086 { 0087 positionToFilthy |= calculateNodePosition(leaf); 0088 0089 registerChangeRect(leaf, positionToFilthy); 0090 0091 KisProjectionLeafSP nextLeaf = leaf->nextSibling(); 0092 if (nextLeaf) 0093 visitHigherNode(nextLeaf, N_ABOVE_FILTHY); 0094 else if (leaf->parent()) 0095 startTripImpl(leaf->parent(), DEFAULT); 0096 0097 registerNeedRect(leaf, positionToFilthy); 0098 } 0099 0100 void KisMergeWalker::visitLowerNode(KisProjectionLeafSP leaf) 0101 { 0102 NodePosition position = 0103 N_BELOW_FILTHY | calculateNodePosition(leaf); 0104 registerNeedRect(leaf, position); 0105 0106 KisProjectionLeafSP prevLeaf = leaf->prevSibling(); 0107 if (prevLeaf) 0108 visitLowerNode(prevLeaf); 0109 }