File indexing completed on 2024-05-12 15:58:37

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_projection_leaf.h"
0008 
0009 #include <KoColorSpace.h>
0010 
0011 #include "kis_layer.h"
0012 #include "kis_image.h"
0013 #include "kis_mask.h"
0014 #include "kis_group_layer.h"
0015 #include "kis_selection_mask.h"
0016 #include "kis_adjustment_layer.h"
0017 
0018 #include "krita_utils.h"
0019 
0020 #include "kis_refresh_subtree_walker.h"
0021 #include "kis_async_merger.h"
0022 #include "kis_node_graph_listener.h"
0023 #include "kis_clone_layer.h"
0024 
0025 
0026 struct Q_DECL_HIDDEN KisProjectionLeaf::Private
0027 {
0028     Private(KisNode *_node) : node(_node) {}
0029 
0030     KisNodeWSP node;
0031     bool isTemporaryHidden = false;
0032 
0033     static bool checkPassThrough(const KisNode *node) {
0034         const KisGroupLayer *group = qobject_cast<const KisGroupLayer*>(node);
0035         return group && group->passThroughMode();
0036     }
0037 
0038     static bool isSelectionMask(const KisNode *node) {
0039         return qobject_cast<const KisSelectionMask*>(node);
0040     }
0041 
0042     static KisNodeSP skipSelectionMasksForward(KisNodeSP node) {
0043         while (node && isSelectionMask(node)) {
0044             node = node->nextSibling();
0045         }
0046         return node;
0047     }
0048 
0049     static KisNodeSP skipSelectionMasksBackward(KisNodeSP node) {
0050         while (node && isSelectionMask(node)) {
0051             node = node->prevSibling();
0052         }
0053         return node;
0054     }
0055 
0056     bool checkParentPassThrough() {
0057         return node->parent() && checkPassThrough(node->parent());
0058     }
0059 
0060     bool checkThisPassThrough() {
0061         return checkPassThrough(node);
0062     }
0063 
0064     KisProjectionLeafSP overlayProjectionLeaf() const {
0065         return node && node->graphListener() && node->graphListener()->graphOverlayNode() ?
0066             node->graphListener()->graphOverlayNode()->projectionLeaf() : 0;
0067     }
0068 
0069     bool isTopmostNode() const {
0070         return !skipSelectionMasksForward(node->nextSibling()) &&
0071             node->parent() &&
0072             !node->parent()->parent();
0073     }
0074 
0075     KisNodeSP findRoot() const {
0076         KisNodeSP root = node;
0077 
0078         while (root->parent()) {
0079             root = root->parent();
0080         }
0081 
0082         return root;
0083     }
0084 
0085     void temporarySetPassThrough(bool value) {
0086         KisGroupLayer *group = qobject_cast<KisGroupLayer*>(node.data());
0087         if (!group) return;
0088 
0089         group->setPassThroughMode(value);
0090     }
0091 };
0092 
0093 KisProjectionLeaf::KisProjectionLeaf(KisNode *node)
0094     : m_d(new Private(node))
0095 {
0096 }
0097 
0098 KisProjectionLeaf::~KisProjectionLeaf()
0099 {
0100 }
0101 
0102 KisProjectionLeafSP KisProjectionLeaf::parent() const
0103 {
0104     KisNodeSP node;
0105 
0106     if (Private::isSelectionMask(m_d->node)) {
0107         if (m_d->overlayProjectionLeaf() == this) {
0108             node = m_d->findRoot();
0109         }
0110     } else {
0111         node = m_d->node->parent();
0112     }
0113 
0114     while (node && Private::checkPassThrough(node)) {
0115         node = node->parent();
0116     }
0117 
0118     return node ? node->projectionLeaf() : KisProjectionLeafSP();
0119 }
0120 
0121 
0122 KisProjectionLeafSP KisProjectionLeaf::firstChild() const
0123 {
0124     KisNodeSP node;
0125 
0126     if (!m_d->checkThisPassThrough()) {
0127         node = m_d->node->firstChild();
0128         node = Private::skipSelectionMasksForward(node);
0129     }
0130 
0131     if (!node && isRoot()) {
0132         KisProjectionLeafSP overlayLeaf = m_d->overlayProjectionLeaf();
0133         if (overlayLeaf) {
0134             return overlayLeaf;
0135         }
0136     }
0137 
0138     return node ? node->projectionLeaf() : KisProjectionLeafSP();
0139 }
0140 
0141 KisProjectionLeafSP KisProjectionLeaf::lastChild() const
0142 {
0143     KisNodeSP node;
0144 
0145     if (isRoot()) {
0146         KisProjectionLeafSP overlayLeaf = m_d->overlayProjectionLeaf();
0147         if (overlayLeaf) {
0148             return overlayLeaf;
0149         }
0150     }
0151 
0152     if (!m_d->checkThisPassThrough()) {
0153         node = m_d->node->lastChild();
0154         node = Private::skipSelectionMasksBackward(node);
0155     }
0156 
0157     return node ? node->projectionLeaf() : KisProjectionLeafSP();
0158 }
0159 
0160 KisProjectionLeafSP KisProjectionLeaf::prevSibling() const
0161 {
0162     if (Private::isSelectionMask(m_d->node)) {
0163         KisProjectionLeafSP leaf;
0164 
0165         if (m_d->overlayProjectionLeaf() == this) {
0166             KisNodeSP node = m_d->findRoot()->lastChild();
0167             node = Private::skipSelectionMasksBackward(node);
0168             leaf = node->projectionLeaf();
0169         }
0170 
0171         return leaf;
0172     }
0173 
0174     KisNodeSP node;
0175 
0176     if (m_d->checkThisPassThrough()) {
0177         node = m_d->node->lastChild();
0178         node = Private::skipSelectionMasksBackward(node);
0179     }
0180 
0181     if (!node) {
0182         node = m_d->node->prevSibling();
0183         node = Private::skipSelectionMasksBackward(node);
0184     }
0185 
0186     const KisProjectionLeaf *leaf = this;
0187     while (!node && leaf->m_d->checkParentPassThrough()) {
0188         leaf = leaf->node()->parent()->projectionLeaf().data();
0189         node = leaf->node()->prevSibling();
0190         node = Private::skipSelectionMasksBackward(node);
0191     }
0192 
0193     return node ? node->projectionLeaf() : KisProjectionLeafSP();
0194 }
0195 
0196 KisProjectionLeafSP KisProjectionLeaf::nextSibling() const
0197 {
0198     if (Private::isSelectionMask(m_d->node)) {
0199         return KisProjectionLeafSP();
0200     }
0201 
0202     KisProjectionLeafSP overlayLeaf = m_d->overlayProjectionLeaf();
0203     if (overlayLeaf && m_d->isTopmostNode()) {
0204         return overlayLeaf;
0205     }
0206 
0207     KisNodeSP node = m_d->node->nextSibling();
0208     node = Private::skipSelectionMasksForward(node);
0209 
0210     while (node && Private::checkPassThrough(node) && node->firstChild()) {
0211         node = node->firstChild();
0212         node = Private::skipSelectionMasksForward(node);
0213     }
0214 
0215     if (!node && m_d->checkParentPassThrough()) {
0216         node = m_d->node->parent();
0217         node = Private::skipSelectionMasksForward(node);
0218     }
0219 
0220     return node ? node->projectionLeaf() : KisProjectionLeafSP();
0221 }
0222 
0223 KisNodeSP KisProjectionLeaf::node() const
0224 {
0225     return m_d->node;
0226 }
0227 
0228 KisAbstractProjectionPlaneSP KisProjectionLeaf::projectionPlane() const
0229 {
0230     return m_d->node->projectionPlane();
0231 }
0232 
0233 bool KisProjectionLeaf::accept(KisNodeVisitor &visitor)
0234 {
0235     return m_d->node->accept(visitor);
0236 }
0237 
0238 KisPaintDeviceSP KisProjectionLeaf::original()
0239 {
0240     return m_d->node->original();
0241 }
0242 
0243 KisPaintDeviceSP KisProjectionLeaf::projection()
0244 {
0245     return m_d->node->projection();
0246 }
0247 
0248 KisPaintDeviceSP KisProjectionLeaf::lazyDestinationForSubtreeComposition()
0249 {
0250     const KisGroupLayer *group = qobject_cast<const KisGroupLayer*>(m_d->node.data());
0251     return group ? group->lazyDestinationForSubtreeComposition() : nullptr;
0252 }
0253 
0254 bool KisProjectionLeaf::isRoot() const
0255 {
0256     return (bool)!m_d->node->parent();
0257 }
0258 
0259 bool KisProjectionLeaf::isLayer() const
0260 {
0261     return (bool)qobject_cast<const KisLayer*>(m_d->node.data()) &&
0262         !m_d->node->isFakeNode();
0263 }
0264 
0265 bool KisProjectionLeaf::isMask() const
0266 {
0267     return (bool)qobject_cast<const KisMask*>(m_d->node.data()) &&
0268         !m_d->node->isFakeNode();
0269 }
0270 
0271 bool KisProjectionLeaf::canHaveChildLayers() const
0272 {
0273     return (bool)qobject_cast<const KisGroupLayer*>(m_d->node.data());
0274 }
0275 
0276 bool KisProjectionLeaf::dependsOnLowerNodes() const
0277 {
0278     return (bool)qobject_cast<const KisAdjustmentLayer*>(m_d->node.data());
0279 }
0280 
0281 bool KisProjectionLeaf::visible() const
0282 {
0283     if (m_d->isTemporaryHidden || isDroppedNode()) return false;
0284 
0285     // TODO: check opacity as well!
0286 
0287     bool hiddenByParentPassThrough = false;
0288 
0289     KisNodeSP node = m_d->node->parent();
0290     while (node && node->projectionLeaf()->m_d->checkThisPassThrough()) {
0291         hiddenByParentPassThrough |= !node->visible();
0292         node = node->parent();
0293     }
0294 
0295     return (m_d->node->visible(false) || m_d->node->isIsolatedRoot()) &&
0296         !m_d->checkThisPassThrough() &&
0297         !hiddenByParentPassThrough;
0298 }
0299 
0300 quint8 KisProjectionLeaf::opacity() const
0301 {
0302     quint8 resultOpacity = m_d->node->opacity();
0303 
0304     if (m_d->checkParentPassThrough()) {
0305         quint8 parentOpacity = m_d->node->parent()->projectionLeaf()->opacity();
0306 
0307         resultOpacity = KritaUtils::mergeOpacity(resultOpacity, parentOpacity);
0308     }
0309 
0310     return resultOpacity;
0311 }
0312 
0313 QBitArray KisProjectionLeaf::channelFlags() const
0314 {
0315     QBitArray channelFlags;
0316 
0317     KisLayer *layer = qobject_cast<KisLayer*>(m_d->node.data());
0318     if (!layer) return channelFlags;
0319 
0320     channelFlags = layer->channelFlags();
0321 
0322     if (m_d->checkParentPassThrough()) {
0323         QBitArray parentChannelFlags;
0324 
0325         if (*m_d->node->colorSpace() ==
0326             *m_d->node->parent()->colorSpace()) {
0327 
0328             KisLayer *parentLayer = qobject_cast<KisLayer*>(m_d->node->parent().data());
0329             parentChannelFlags = parentLayer->channelFlags();
0330         }
0331 
0332         channelFlags = KritaUtils::mergeChannelFlags(channelFlags, parentChannelFlags);
0333     }
0334 
0335     return channelFlags;
0336 }
0337 
0338 bool KisProjectionLeaf::isStillInGraph() const
0339 {
0340     return (bool)m_d->node->graphListener();
0341 }
0342 
0343 bool KisProjectionLeaf::hasClones() const
0344 {
0345     KisLayer *layer = qobject_cast<KisLayer*>(m_d->node.data());
0346     return layer ? layer->hasClones() : false;
0347 }
0348 
0349 bool KisProjectionLeaf::isDroppedNode() const
0350 {
0351     return dropReason() != NodeAvailable;
0352 }
0353 
0354 bool KisProjectionLeaf::shouldBeRendered() const
0355 {
0356     return visible() || hasClones();
0357 }
0358 
0359 KisProjectionLeaf::NodeDropReason KisProjectionLeaf::dropReason() const
0360 {
0361     if (qobject_cast<KisMask*>(m_d->node.data()) &&
0362             m_d->checkParentPassThrough()) {
0363 
0364         return DropPassThroughMask;
0365     }
0366 
0367     KisCloneLayer *cloneLayer = qobject_cast<KisCloneLayer*>(m_d->node.data());
0368     if (cloneLayer && cloneLayer->copyFrom()) {
0369         KisProjectionLeafSP leaf = cloneLayer->copyFrom()->projectionLeaf();
0370 
0371         if (leaf->m_d->checkThisPassThrough()) {
0372             return DropPassThroughClone;
0373         }
0374     }
0375 
0376     return NodeAvailable;
0377 }
0378 
0379 bool KisProjectionLeaf::isOverlayProjectionLeaf() const
0380 {
0381     return this == m_d->overlayProjectionLeaf();
0382 }
0383 
0384 void KisProjectionLeaf::setTemporaryHiddenFromRendering(bool value)
0385 {
0386     m_d->isTemporaryHidden = value;
0387 }
0388 
0389 bool KisProjectionLeaf::isTemporaryHiddenFromRendering() const
0390 {
0391     return m_d->isTemporaryHidden;
0392 }
0393 
0394 /**
0395  * This method is rather slow and dangerous. It should be executes in
0396  * exclusive environment only.
0397  */
0398 void KisProjectionLeaf::explicitlyRegeneratePassThroughProjection()
0399 {
0400     if (!m_d->checkThisPassThrough()) return;
0401 
0402     m_d->temporarySetPassThrough(false);
0403 
0404     const QRect updateRect = projection()->defaultBounds()->bounds();
0405 
0406     KisRefreshSubtreeWalker walker(updateRect);
0407     walker.collectRects(m_d->node, updateRect);
0408 
0409     KisAsyncMerger merger;
0410     merger.startMerge(walker);
0411 
0412     m_d->temporarySetPassThrough(true);
0413 }