File indexing completed on 2024-05-12 15:58:28
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_node.h" 0008 0009 #include <QList> 0010 #include <QReadWriteLock> 0011 #include <QReadLocker> 0012 #include <QWriteLocker> 0013 #include <QPainterPath> 0014 #include <QRect> 0015 #include <QCoreApplication> 0016 0017 #include <KoProperties.h> 0018 0019 #include "kis_global.h" 0020 #include "kis_node_graph_listener.h" 0021 #include "kis_node_visitor.h" 0022 #include "kis_processing_visitor.h" 0023 #include "kis_node_progress_proxy.h" 0024 #include "kis_busy_progress_indicator.h" 0025 0026 #include "kis_clone_layer.h" 0027 0028 #include "kis_time_span.h" 0029 0030 #include "kis_safe_read_list.h" 0031 typedef KisSafeReadList<KisNodeSP> KisSafeReadNodeList; 0032 0033 #include "kis_abstract_projection_plane.h" 0034 #include "kis_projection_leaf.h" 0035 #include "kis_undo_adapter.h" 0036 #include "kis_keyframe_channel.h" 0037 #include "kis_image.h" 0038 #include "kis_layer_utils.h" 0039 #include "KisRegion.h" 0040 0041 /** 0042 *The link between KisProjection and KisImageUpdater 0043 *uses queued signals with an argument of KisNodeSP type, 0044 *so we should register it beforehand 0045 */ 0046 struct KisNodeSPStaticRegistrar { 0047 KisNodeSPStaticRegistrar() { 0048 qRegisterMetaType<KisNodeSP>("KisNodeSP"); 0049 } 0050 }; 0051 static KisNodeSPStaticRegistrar __registrar1; 0052 0053 struct KisNodeListStaticRegistrar { 0054 KisNodeListStaticRegistrar() { 0055 qRegisterMetaType<KisNodeList>("KisNodeList"); 0056 } 0057 }; 0058 static KisNodeListStaticRegistrar __registrar2; 0059 0060 0061 /** 0062 * Note about "thread safety" of KisNode 0063 * 0064 * 1) One can *read* any information about node and node graph in any 0065 * number of threads concurrently. This operation is safe because 0066 * of the usage of KisSafeReadNodeList and will run concurrently 0067 * (lock-free). 0068 * 0069 * 2) One can *write* any information into the node or node graph in a 0070 * single thread only! Changing the graph concurrently is *not* 0071 * sane and therefore not supported. 0072 * 0073 * 3) One can *read and write* information about the node graph 0074 * concurrently, given that there is only *one* writer thread and 0075 * any number of reader threads. Please note that in this case the 0076 * node's code is just guaranteed *not to crash*, which is ensured 0077 * by nodeSubgraphLock. You need to ensure the sanity of the data 0078 * read by the reader threads yourself! 0079 */ 0080 0081 struct Q_DECL_HIDDEN KisNode::Private 0082 { 0083 public: 0084 Private(KisNode *node) 0085 : graphListener(0) 0086 , nodeProgressProxy(0) 0087 , busyProgressIndicator(0) 0088 , projectionLeaf(new KisProjectionLeaf(node)) 0089 { 0090 } 0091 0092 KisNodeWSP parent; 0093 KisNodeGraphListener *graphListener; 0094 KisSafeReadNodeList nodes; 0095 KisNodeProgressProxy *nodeProgressProxy; 0096 KisBusyProgressIndicator *busyProgressIndicator; 0097 QReadWriteLock nodeSubgraphLock; 0098 0099 KisProjectionLeafSP projectionLeaf; 0100 0101 const KisNode* findSymmetricClone(const KisNode *srcRoot, 0102 const KisNode *dstRoot, 0103 const KisNode *srcTarget); 0104 void processDuplicatedClones(const KisNode *srcDuplicationRoot, 0105 const KisNode *dstDuplicationRoot, 0106 KisNode *node); 0107 }; 0108 0109 /** 0110 * Finds the layer in \p dstRoot subtree, which has the same path as 0111 * \p srcTarget has in \p srcRoot 0112 */ 0113 const KisNode* KisNode::Private::findSymmetricClone(const KisNode *srcRoot, 0114 const KisNode *dstRoot, 0115 const KisNode *srcTarget) 0116 { 0117 if (srcRoot == srcTarget) return dstRoot; 0118 0119 KisSafeReadNodeList::const_iterator srcIter = srcRoot->m_d->nodes.constBegin(); 0120 KisSafeReadNodeList::const_iterator dstIter = dstRoot->m_d->nodes.constBegin(); 0121 0122 for (; srcIter != srcRoot->m_d->nodes.constEnd(); srcIter++, dstIter++) { 0123 0124 KIS_ASSERT_RECOVER_RETURN_VALUE((srcIter != srcRoot->m_d->nodes.constEnd()) == 0125 (dstIter != dstRoot->m_d->nodes.constEnd()), 0); 0126 0127 const KisNode *node = findSymmetricClone(srcIter->data(), dstIter->data(), srcTarget); 0128 if (node) return node; 0129 0130 } 0131 0132 return 0; 0133 } 0134 0135 /** 0136 * This function walks through a subtrees of old and new layers and 0137 * searches for clone layers. For each clone layer it checks whether 0138 * its copyFrom() lays inside the old subtree, and if it is so resets 0139 * it to the corresponding layer in the new subtree. 0140 * 0141 * That is needed when the user duplicates a group layer with all its 0142 * layer subtree. In such a case all the "internal" clones must stay 0143 * "internal" and not point to the layers of the older group. 0144 */ 0145 void KisNode::Private::processDuplicatedClones(const KisNode *srcDuplicationRoot, 0146 const KisNode *dstDuplicationRoot, 0147 KisNode *node) 0148 { 0149 if (KisCloneLayer *clone = dynamic_cast<KisCloneLayer*>(node)) { 0150 KIS_ASSERT_RECOVER_RETURN(clone->copyFrom()); 0151 const KisNode *newCopyFrom = findSymmetricClone(srcDuplicationRoot, 0152 dstDuplicationRoot, 0153 clone->copyFrom()); 0154 0155 if (newCopyFrom) { 0156 KisLayer *newCopyFromLayer = qobject_cast<KisLayer*>(const_cast<KisNode*>(newCopyFrom)); 0157 KIS_ASSERT_RECOVER_RETURN(newCopyFromLayer); 0158 0159 clone->setCopyFrom(newCopyFromLayer); 0160 } 0161 } 0162 0163 KisSafeReadNodeList::const_iterator iter; 0164 FOREACH_SAFE(iter, node->m_d->nodes) { 0165 KisNode *child = const_cast<KisNode*>((*iter).data()); 0166 processDuplicatedClones(srcDuplicationRoot, dstDuplicationRoot, child); 0167 } 0168 } 0169 0170 KisNode::KisNode(KisImageWSP image) 0171 : KisBaseNode(image), 0172 m_d(new Private(this)) 0173 { 0174 m_d->parent = 0; 0175 m_d->graphListener = 0; 0176 moveToThread(qApp->thread()); 0177 } 0178 0179 KisNode::KisNode(const KisNode & rhs) 0180 : KisBaseNode(rhs) 0181 , m_d(new Private(this)) 0182 { 0183 m_d->parent = 0; 0184 m_d->graphListener = 0; 0185 moveToThread(qApp->thread()); 0186 0187 // NOTE: the nodes are not supposed to be added/removed while 0188 // creation of another node, so we do *no* locking here! 0189 0190 KisSafeReadNodeList::const_iterator iter; 0191 FOREACH_SAFE(iter, rhs.m_d->nodes) { 0192 KisNodeSP child = (*iter)->clone(); 0193 child->createNodeProgressProxy(); 0194 m_d->nodes.append(child); 0195 child->setParent(this); 0196 } 0197 0198 m_d->processDuplicatedClones(&rhs, this, this); 0199 } 0200 0201 KisNode::~KisNode() 0202 { 0203 if (m_d->busyProgressIndicator) { 0204 m_d->busyProgressIndicator->prepareDestroying(); 0205 m_d->busyProgressIndicator->deleteLater(); 0206 } 0207 0208 if (m_d->nodeProgressProxy) { 0209 m_d->nodeProgressProxy->prepareDestroying(); 0210 m_d->nodeProgressProxy->deleteLater(); 0211 } 0212 0213 { 0214 QWriteLocker l(&m_d->nodeSubgraphLock); 0215 m_d->nodes.clear(); 0216 } 0217 0218 delete m_d; 0219 } 0220 0221 QRect KisNode::needRect(const QRect &rect, PositionToFilthy pos) const 0222 { 0223 Q_UNUSED(pos); 0224 return rect; 0225 } 0226 0227 QRect KisNode::changeRect(const QRect &rect, PositionToFilthy pos) const 0228 { 0229 Q_UNUSED(pos); 0230 return rect; 0231 } 0232 0233 QRect KisNode::accessRect(const QRect &rect, PositionToFilthy pos) const 0234 { 0235 Q_UNUSED(pos); 0236 return rect; 0237 } 0238 0239 void KisNode::childNodeChanged(KisNodeSP /*changedChildNode*/) 0240 { 0241 } 0242 0243 KisAbstractProjectionPlaneSP KisNode::projectionPlane() const 0244 { 0245 KIS_ASSERT_RECOVER_NOOP(0 && "KisNode::projectionPlane() is not defined!"); 0246 static KisAbstractProjectionPlaneSP plane = 0247 toQShared(new KisDumbProjectionPlane()); 0248 0249 return plane; 0250 } 0251 0252 KisProjectionLeafSP KisNode::projectionLeaf() const 0253 { 0254 return m_d->projectionLeaf; 0255 } 0256 0257 void KisNode::setImage(KisImageWSP newImage) 0258 { 0259 KisBaseNode::setImage(newImage); 0260 0261 KisNodeSP node = firstChild(); 0262 while (node) { 0263 KisLayerUtils::recursiveApplyNodes(node, 0264 [newImage] (KisNodeSP node) { 0265 node->setImage(newImage); 0266 }); 0267 0268 node = node->nextSibling(); 0269 } 0270 } 0271 0272 bool KisNode::accept(KisNodeVisitor &v) 0273 { 0274 return v.visit(this); 0275 } 0276 0277 void KisNode::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) 0278 { 0279 visitor.visit(this, undoAdapter); 0280 } 0281 0282 int KisNode::graphSequenceNumber() const 0283 { 0284 return m_d->graphListener ? m_d->graphListener->graphSequenceNumber() : -1; 0285 } 0286 0287 KisNodeGraphListener *KisNode::graphListener() const 0288 { 0289 return m_d->graphListener; 0290 } 0291 0292 void KisNode::setGraphListener(KisNodeGraphListener *graphListener) 0293 { 0294 m_d->graphListener = graphListener; 0295 0296 QReadLocker l(&m_d->nodeSubgraphLock); 0297 KisSafeReadNodeList::const_iterator iter; 0298 FOREACH_SAFE(iter, m_d->nodes) { 0299 KisNodeSP child = (*iter); 0300 child->setGraphListener(graphListener); 0301 } 0302 } 0303 0304 void KisNode::setParent(KisNodeWSP parent) 0305 { 0306 QWriteLocker l(&m_d->nodeSubgraphLock); 0307 m_d->parent = parent; 0308 } 0309 0310 KisNodeSP KisNode::parent() const 0311 { 0312 QReadLocker l(&m_d->nodeSubgraphLock); 0313 return m_d->parent.isValid() ? KisNodeSP(m_d->parent) : KisNodeSP(); 0314 } 0315 0316 KisBaseNodeSP KisNode::parentCallback() const 0317 { 0318 return parent(); 0319 } 0320 0321 void KisNode::notifyParentVisibilityChanged(bool value) 0322 { 0323 QReadLocker l(&m_d->nodeSubgraphLock); 0324 0325 KisSafeReadNodeList::const_iterator iter; 0326 FOREACH_SAFE(iter, m_d->nodes) { 0327 KisNodeSP child = (*iter); 0328 child->notifyParentVisibilityChanged(value); 0329 } 0330 } 0331 0332 void KisNode::baseNodeChangedCallback() 0333 { 0334 if(m_d->graphListener) { 0335 m_d->graphListener->nodeChanged(this); 0336 emit sigNodeChangedInternal(); 0337 } 0338 } 0339 0340 void KisNode::baseNodeInvalidateAllFramesCallback() 0341 { 0342 if(m_d->graphListener) { 0343 m_d->graphListener->invalidateAllFrames(); 0344 } 0345 } 0346 0347 void KisNode::baseNodeCollapsedChangedCallback() 0348 { 0349 if(m_d->graphListener) { 0350 m_d->graphListener->nodeCollapsedChanged(this); 0351 } 0352 } 0353 0354 void KisNode::addKeyframeChannel(KisKeyframeChannel *channel) 0355 { 0356 channel->setNode(this); 0357 KisBaseNode::addKeyframeChannel(channel); 0358 0359 if (m_d->graphListener) { 0360 m_d->graphListener->keyframeChannelHasBeenAdded(this, channel); 0361 } 0362 } 0363 0364 KisNodeSP KisNode::firstChild() const 0365 { 0366 QReadLocker l(&m_d->nodeSubgraphLock); 0367 return !m_d->nodes.isEmpty() ? m_d->nodes.first() : 0; 0368 } 0369 0370 KisNodeSP KisNode::lastChild() const 0371 { 0372 QReadLocker l(&m_d->nodeSubgraphLock); 0373 return !m_d->nodes.isEmpty() ? m_d->nodes.last() : 0; 0374 } 0375 0376 KisNodeSP KisNode::prevChildImpl(KisNodeSP child) 0377 { 0378 /** 0379 * Warning: mind locking policy! 0380 * 0381 * The graph locks must be *always* taken in descending 0382 * order. That is if you want to (or it implicitly happens that 0383 * you) take a lock of a parent and a chil, you must first take 0384 * the lock of a parent, and only after that ask a child to do the 0385 * same. Otherwise you'll get a deadlock. 0386 */ 0387 0388 QReadLocker l(&m_d->nodeSubgraphLock); 0389 0390 int i = m_d->nodes.indexOf(child) - 1; 0391 return i >= 0 ? m_d->nodes.at(i) : 0; 0392 } 0393 0394 KisNodeSP KisNode::nextChildImpl(KisNodeSP child) 0395 { 0396 /** 0397 * See a comment in KisNode::prevChildImpl() 0398 */ 0399 QReadLocker l(&m_d->nodeSubgraphLock); 0400 0401 int i = m_d->nodes.indexOf(child) + 1; 0402 return i > 0 && i < m_d->nodes.size() ? m_d->nodes.at(i) : 0; 0403 } 0404 0405 KisNodeSP KisNode::prevSibling() const 0406 { 0407 KisNodeSP parentNode = parent(); 0408 return parentNode ? parentNode->prevChildImpl(const_cast<KisNode*>(this)) : 0; 0409 } 0410 0411 KisNodeSP KisNode::nextSibling() const 0412 { 0413 KisNodeSP parentNode = parent(); 0414 return parentNode ? parentNode->nextChildImpl(const_cast<KisNode*>(this)) : 0; 0415 } 0416 0417 quint32 KisNode::childCount() const 0418 { 0419 QReadLocker l(&m_d->nodeSubgraphLock); 0420 return m_d->nodes.size(); 0421 } 0422 0423 0424 KisNodeSP KisNode::at(quint32 index) const 0425 { 0426 QReadLocker l(&m_d->nodeSubgraphLock); 0427 0428 if (!m_d->nodes.isEmpty() && index < (quint32)m_d->nodes.size()) { 0429 return m_d->nodes.at(index); 0430 } 0431 0432 return 0; 0433 } 0434 0435 int KisNode::index(const KisNodeSP node) const 0436 { 0437 QReadLocker l(&m_d->nodeSubgraphLock); 0438 0439 return m_d->nodes.indexOf(node); 0440 } 0441 0442 QList<KisNodeSP> KisNode::childNodes(const QStringList & nodeTypes, const KoProperties & properties) const 0443 { 0444 QReadLocker l(&m_d->nodeSubgraphLock); 0445 0446 QList<KisNodeSP> nodes; 0447 0448 KisSafeReadNodeList::const_iterator iter; 0449 FOREACH_SAFE(iter, m_d->nodes) { 0450 if (*iter) { 0451 if (properties.isEmpty() || (*iter)->check(properties)) { 0452 bool rightType = true; 0453 0454 if(!nodeTypes.isEmpty()) { 0455 rightType = false; 0456 Q_FOREACH (const QString &nodeType, nodeTypes) { 0457 if ((*iter)->inherits(nodeType.toLatin1())) { 0458 rightType = true; 0459 break; 0460 } 0461 } 0462 } 0463 if (rightType) { 0464 nodes.append(*iter); 0465 } 0466 } 0467 } 0468 } 0469 return nodes; 0470 } 0471 0472 KisNodeSP KisNode::findChildByName(const QString &name) 0473 { 0474 KisNodeSP child = firstChild(); 0475 while (child) { 0476 if (child->name() == name) { 0477 return child; 0478 } 0479 if (child->childCount() > 0) { 0480 KisNodeSP grandChild = child->findChildByName(name); 0481 if (grandChild) { 0482 return grandChild; 0483 } 0484 } 0485 child = child->nextSibling(); 0486 } 0487 return 0; 0488 } 0489 0490 KisNodeSP KisNode::findChildByUniqueID(const QUuid &uuid) 0491 { 0492 KisNodeSP child = firstChild(); 0493 while (child) { 0494 if (child->uuid() == uuid) { 0495 return child; 0496 } 0497 if (child->childCount() > 0) { 0498 KisNodeSP grandChild = child->findChildByUniqueID(uuid); 0499 if (grandChild) { 0500 return grandChild; 0501 } 0502 } 0503 child = child->nextSibling(); 0504 } 0505 return 0; 0506 } 0507 0508 bool KisNode::add(KisNodeSP newNode, KisNodeSP aboveThis) 0509 { 0510 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(newNode, false); 0511 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!aboveThis || aboveThis->parent().data() == this, false); 0512 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(allowAsChild(newNode), false); 0513 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!newNode->parent(), false); 0514 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(index(newNode) < 0, false); 0515 0516 int idx = aboveThis ? this->index(aboveThis) + 1 : 0; 0517 0518 // threoretical race condition may happen here ('idx' may become 0519 // deprecated until the write lock will be held). But we ignore 0520 // it, because it is not supported to add/remove nodes from two 0521 // concurrent threads simultaneously 0522 0523 if (m_d->graphListener) { 0524 m_d->graphListener->aboutToAddANode(this, idx); 0525 } 0526 0527 { 0528 QWriteLocker l(&m_d->nodeSubgraphLock); 0529 0530 newNode->createNodeProgressProxy(); 0531 0532 m_d->nodes.insert(idx, newNode); 0533 0534 newNode->setParent(this); 0535 newNode->setGraphListener(m_d->graphListener); 0536 } 0537 0538 newNode->setImage(image()); 0539 0540 if (m_d->graphListener) { 0541 m_d->graphListener->nodeHasBeenAdded(this, idx); 0542 } 0543 0544 childNodeChanged(newNode); 0545 0546 return true; 0547 } 0548 0549 bool KisNode::remove(quint32 index) 0550 { 0551 if (index < childCount()) { 0552 KisNodeSP removedNode = at(index); 0553 0554 if (m_d->graphListener) { 0555 m_d->graphListener->aboutToRemoveANode(this, index); 0556 } 0557 0558 removedNode->setImage(0); 0559 0560 { 0561 QWriteLocker l(&m_d->nodeSubgraphLock); 0562 0563 removedNode->setGraphListener(0); 0564 0565 removedNode->setParent(0); // after calling aboutToRemoveANode or then the model get broken according to TT's modeltest 0566 m_d->nodes.removeAt(index); 0567 } 0568 0569 if (m_d->graphListener) { 0570 m_d->graphListener->nodeHasBeenRemoved(this, index); 0571 } 0572 0573 childNodeChanged(removedNode); 0574 0575 return true; 0576 } 0577 return false; 0578 } 0579 0580 bool KisNode::remove(KisNodeSP node) 0581 { 0582 return node->parent().data() == this ? remove(index(node)) : false; 0583 } 0584 0585 KisNodeProgressProxy* KisNode::nodeProgressProxy() const 0586 { 0587 if (m_d->nodeProgressProxy) { 0588 return m_d->nodeProgressProxy; 0589 } else if (parent()) { 0590 return parent()->nodeProgressProxy(); 0591 } 0592 return 0; 0593 } 0594 0595 KisBusyProgressIndicator* KisNode::busyProgressIndicator() const 0596 { 0597 if (m_d->busyProgressIndicator) { 0598 return m_d->busyProgressIndicator; 0599 } else if (parent()) { 0600 return parent()->busyProgressIndicator(); 0601 } 0602 return 0; 0603 } 0604 0605 void KisNode::createNodeProgressProxy() 0606 { 0607 if (!m_d->nodeProgressProxy) { 0608 m_d->nodeProgressProxy = new KisNodeProgressProxy(this); 0609 m_d->busyProgressIndicator = new KisBusyProgressIndicator(m_d->nodeProgressProxy); 0610 0611 m_d->nodeProgressProxy->moveToThread(this->thread()); 0612 m_d->busyProgressIndicator->moveToThread(this->thread()); 0613 } 0614 } 0615 0616 void KisNode::setDirty() 0617 { 0618 setDirty(extent()); 0619 } 0620 0621 void KisNode::setDirty(const QVector<QRect> &rects) 0622 { 0623 if(m_d->graphListener) { 0624 m_d->graphListener->requestProjectionUpdate(this, rects, true); 0625 } 0626 } 0627 0628 void KisNode::setDirty(const KisRegion ®ion) 0629 { 0630 setDirty(region.rects()); 0631 } 0632 0633 void KisNode::setDirty(const QRect & rect) 0634 { 0635 setDirty(QVector<QRect>({rect})); 0636 } 0637 0638 void KisNode::setDirtyDontResetAnimationCache() 0639 { 0640 setDirtyDontResetAnimationCache(QVector<QRect>({extent()})); 0641 } 0642 0643 void KisNode::setDirtyDontResetAnimationCache(const QRect &rect) 0644 { 0645 setDirtyDontResetAnimationCache(QVector<QRect>({rect})); 0646 } 0647 0648 void KisNode::setDirtyDontResetAnimationCache(const QVector<QRect> &rects) 0649 { 0650 if(m_d->graphListener) { 0651 m_d->graphListener->requestProjectionUpdate(this, rects, false); 0652 } 0653 } 0654 0655 void KisNode::invalidateFrames(const KisTimeSpan &range, const QRect &rect) 0656 { 0657 if(m_d->graphListener) { 0658 m_d->graphListener->invalidateFrames(range, rect); 0659 } 0660 } 0661 0662 void KisNode::handleKeyframeChannelUpdate(const KisTimeSpan &range, const QRect &rect) 0663 { 0664 invalidateFrames(range, rect); 0665 0666 if (image()) { 0667 KisDefaultBoundsSP bounds(new KisDefaultBounds(image())); 0668 0669 if (range.contains(bounds->currentTime())) { 0670 setDirty(rect); 0671 } 0672 } 0673 } 0674 0675 void KisNode::requestTimeSwitch(int time) 0676 { 0677 if(m_d->graphListener) { 0678 m_d->graphListener->requestTimeSwitch(time); 0679 } 0680 } 0681 0682 void KisNode::syncLodCache() 0683 { 0684 // noop. everything is done by getLodCapableDevices() 0685 } 0686 0687 KisPaintDeviceList KisNode::getLodCapableDevices() const 0688 { 0689 KisPaintDeviceList list; 0690 0691 KisPaintDeviceSP device = paintDevice(); 0692 if (device) { 0693 list << device; 0694 } 0695 0696 KisPaintDeviceSP originalDevice = original(); 0697 if (originalDevice && originalDevice != device) { 0698 list << originalDevice; 0699 } 0700 0701 list << projectionPlane()->getLodCapableDevices(); 0702 0703 return list; 0704 }